Thread: [myhdl-list] [PATCH] Remove redundant copy operators
Brought to you by:
jandecaluwe
From: Ben <ben...@gm...> - 2009-11-03 15:08:12
Attachments:
copy.hg
|
Hi there, First of all, hello to everyone, and thanks for this great initiative which is MyHDL, till now, I enjoyed using it. I ran into trouble though when I was looking for VHDL 'alias' ... I was trying to make my code more readable when dealing with ControlWords. The first solution I found is to make a always_comb process, but still, we have to use a .next, so we don't have strictly the 'alias' behavior. This solution is sort of driven by my "think hardware" mind, or should I say, education. The second solution I found, and there, MyHDL shows its supremacy, is to use Python as a tool, and not define my ControlWord as intbv, but to define my own class, say ctrlword that inherit from intbv, redefine "__getattr__", such that "ctrlword.subpart3" return the right slice from my intbv. THis also has the advantage that I keep complete compatibility (think conversion) with the intbv type. Clever isnt't it ? The only problem I got is that the intbv __copy__ function was forcing the return value as being an intbv, thus, removing all the information from my ctrlword. As both __copy__ and __deepcopy__ are behaving the same as the Python default one, I was able to remove them, without influencing the testsuite result. (By the way on my MacOSX, I have some test failing with regard to set and Set) Here is a patch that does what I described here. Best Regards Benoit # HG changeset patch # User Benoit Allard <ben...@gm...> # Date 1257160071 -3600 # Node ID bd6b60949b4e68023e41f49ce853c0058e02019b # Parent 2ff17ece613127b174cb7a6a9aa8ba765ffcbd01 Remove useless copy operators The default one are making the same, and even beter. Those one were preventing us to subclass the intbv class, as the copy were forcing the return type to intbv, removing information about our subclass. diff -r 2ff17ece6131 -r bd6b60949b4e myhdl/_intbv.py --- a/myhdl/_intbv.py Tue Oct 06 07:02:37 2009 -0500 +++ b/myhdl/_intbv.py Mon Nov 02 12:07:51 2009 +0100 @@ -90,12 +90,6 @@ def __hash__(self): raise TypeError("intbv objects are unhashable") - # copy methods - def __copy__(self): - return intbv(self) - def __deepcopy__(self, visit): - return intbv(self) - # iterator method def __iter__(self): if not self._nrbits: |
From: Christopher F. <chr...@gm...> - 2009-11-03 16:24:19
|
> > > The first solution I found is to make a always_comb process, but > still, we have to use a .next, so we don't have strictly the 'alias' > behavior. This solution is sort of driven by my "think hardware" mind, > or should I say, education. > > The second solution I found, and there, MyHDL shows its supremacy, is > to use Python as a tool, and not define my ControlWord as intbv, but > to define my own class, say ctrlword that inherit from intbv, redefine > "__getattr__", such that "ctrlword.subpart3" return the right slice > from my intbv. THis also has the advantage that I keep complete > compatibility (think conversion) with the intbv type. Clever isnt't it > ? The only problem I got is that the intbv __copy__ function was > forcing the return value as being an intbv, thus, removing all the > information from my ctrlword. > It might be better to override the methods/functions in your ctlrword class than removing them from the intbv object? I did something similar with the fixed-point object, http://www.myhdl.org/doku.php/users:cfelton:projects:fxintbv, which is convertible, as well. Think this is/has been a sticky issue in the Python community in general. Seems like there are strong opinions one way or the other. In general an inheriting class needs to override all the base class methods to return the new type. I believe you are asserting that the general copy returns the type of the object being copied and there is no need to override the copy methods? .chris |
From: Ben <ben...@gm...> - 2009-11-03 16:48:06
|
Hi Christopher, On Tue, Nov 3, 2009 at 17:24, Christopher Felton <chr...@gm...> wrote: >> >> The first solution I found is to make a always_comb process, but >> still, we have to use a .next, so we don't have strictly the 'alias' >> behavior. This solution is sort of driven by my "think hardware" mind, >> or should I say, education. >> >> The second solution I found, and there, MyHDL shows its supremacy, is >> to use Python as a tool, and not define my ControlWord as intbv, but >> to define my own class, say ctrlword that inherit from intbv, redefine >> "__getattr__", such that "ctrlword.subpart3" return the right slice >> from my intbv. THis also has the advantage that I keep complete >> compatibility (think conversion) with the intbv type. Clever isnt't it >> ? The only problem I got is that the intbv __copy__ function was >> forcing the return value as being an intbv, thus, removing all the >> information from my ctrlword. > > It might be better to override the methods/functions in your ctlrword class > than removing them from the intbv object? I did something similar with the > fixed-point > object, http://www.myhdl.org/doku.php/users:cfelton:projects:fxintbv, which > is convertible, as well. Actually, for completeness, this second solution still need a .next as a slice still is an intbv and isn't a Signal, giving it as parameter to a module kills it Signal nature. I still need to look at what can be done at the Signal level for that. > Think this is/has been a sticky issue in the Python community in general. > Seems like there are strong opinions one way or the other. In general an > inheriting class needs to override all the base class methods to return the > new type. I would understand if the original function needs to do something, actually , looking to the history of the code (thanks mercurial), this function has been created returning a copy of "self._val", where it would have made sense to define it, and later corrected to return a copy of "self", where it doesn't make sense any more to define it as the vanilla __copy__ from Python does the same, but taking care of types. A "good" copy should looks like: def __copy__(self): return self.__class__(self) There, we wouldn't have had troubles. > I believe you are asserting that the general copy returns the type of the > object being copied and there is no need to override the copy methods? That's right ! Even if it sound redundant, a copy of an object returns a /copy/ of the same object : same value, same type. Regards, Benoit |
From: Christopher F. <chr...@gm...> - 2009-11-03 21:36:21
|
On Tue, Nov 3, 2009 at 10:47 AM, Ben <ben...@gm...> wrote: > Hi Christopher, > > On Tue, Nov 3, 2009 at 17:24, Christopher Felton <chr...@gm...> > wrote: > >> > >> The first solution I found is to make a always_comb process, but > >> still, we have to use a .next, so we don't have strictly the 'alias' > >> behavior. This solution is sort of driven by my "think hardware" mind, > >> or should I say, education. > >> > >> The second solution I found, and there, MyHDL shows its supremacy, is > >> to use Python as a tool, and not define my ControlWord as intbv, but > >> to define my own class, say ctrlword that inherit from intbv, redefine > >> "__getattr__", such that "ctrlword.subpart3" return the right slice > >> from my intbv. THis also has the advantage that I keep complete > >> compatibility (think conversion) with the intbv type. Clever isnt't it > >> ? The only problem I got is that the intbv __copy__ function was > >> forcing the return value as being an intbv, thus, removing all the > >> information from my ctrlword. > > > > It might be better to override the methods/functions in your ctlrword > class > > than removing them from the intbv object? I did something similar with > the > > fixed-point > > object, http://www.myhdl.org/doku.php/users:cfelton:projects:fxintbv, > which > > is convertible, as well. > > Actually, for completeness, this second solution still need a .next as > a slice still is an intbv and isn't a Signal, giving it as parameter > to a module kills it Signal nature. I still need to look at what can > be done at the Signal level for that. > > Ok, I am slowing catching on to what you are trying to achieve. In this case you might also have to cinherit the Signal class and override the update method in the Signal class. Currently the Signal class has "next" handlers for the different types. If the type passes isn't support an exception will occur. Since it is a derived class of intbv it will use the default intbv "next handler" Maybe this could be extended so that "type handlers" can be registered without creating a new derived Signal class. I have done this before with numpy arrays but created a new class that inherits Signal and overloaded the update (_setUpdateType). Others might have better suggestions or comments as well. > Think this is/has been a sticky issue in the Python community in general. > > Seems like there are strong opinions one way or the other. In general > an > > inheriting class needs to override all the base class methods to return > the > > new type. > > I would understand if the original function needs to do something, > actually , looking to the history of the code (thanks mercurial), this > function has been created returning a copy of "self._val", where it > would have made sense to define it, and later corrected to return a > copy of "self", where it doesn't make sense any more to define it as > the vanilla __copy__ from Python does the same, but taking care of > types. > > A "good" copy should looks like: > def __copy__(self): > return self.__class__(self) > > There, we wouldn't have had troubles. > > > I believe you are asserting that the general copy returns the type of the > > object being copied and there is no need to override the copy methods? > > That's right ! Even if it sound redundant, a copy of an object returns > a /copy/ of the same object : same value, same type. > That is a good point! As you originally suggested the copy functions are no longer required. .chris |
From: Jan D. <ja...@ja...> - 2009-11-04 11:49:52
|
I'm not entirely sure I understand the issue, but here are some upfront remarks. Something like a VHDL alias in its full generality would probably require Python language support. What we can do is try to accomodate for some limited but interesting cases. One issue that I have addressed myself is the fact the MyHDL signal slices aren't signals. I consider this a major weakness, and I have come up with a proposal to address what I consider the most important issues: http://www.myhdl.org/doku.php/meps:mep-105 An implementation is present in the development trunk. I would be interested to hear whether this can be a solution for you. E.g: class ControlWord(object): pass ctrlword = ControlWord() a = intbv(0)[32:] ctrlword.subpart = a(4, 2) # shadow signal, only for reading, note round brackets Then: with Python you can of course do what you want, very clever tricks. This is abvolutely fine for modeling. However, when you also want Verilog/VHDL convertibility, your options are very limited. E.g. something like the above wouldn't work because signals as attributes are not yet supported by the convertor. However, somethink like: subpart = a(4, 2) would be convertible, because the convertor explicitly supports dedicated conversion code for shadow signals. Finally: the copy methods. I agree that they are not as they should be as they are not compatible with subclassing now. However, there was a a reason to have dedicated copy methods instead of the generic ones: performance. The Signal class is using copy all the time, and it makes a difference. However, I have to think about it again, because now that I look at it it may be done much better for the intbv case. Jan Ben wrote: > Hi there, > > First of all, hello to everyone, and thanks for this great initiative > which is MyHDL, till now, I enjoyed using it. > > I ran into trouble though when I was looking for VHDL 'alias' ... I > was trying to make my code more readable when dealing with > ControlWords. > > The first solution I found is to make a always_comb process, but > still, we have to use a .next, so we don't have strictly the 'alias' > behavior. This solution is sort of driven by my "think hardware" mind, > or should I say, education. > > The second solution I found, and there, MyHDL shows its supremacy, is > to use Python as a tool, and not define my ControlWord as intbv, but > to define my own class, say ctrlword that inherit from intbv, redefine > "__getattr__", such that "ctrlword.subpart3" return the right slice > from my intbv. THis also has the advantage that I keep complete > compatibility (think conversion) with the intbv type. Clever isnt't it > ? The only problem I got is that the intbv __copy__ function was > forcing the return value as being an intbv, thus, removing all the > information from my ctrlword. > > As both __copy__ and __deepcopy__ are behaving the same as the Python > default one, I was able to remove them, without influencing the > testsuite result. (By the way on my MacOSX, I have some test failing > with regard to set and Set) > > Here is a patch that does what I described here. > > Best Regards > Benoit > > # HG changeset patch > # User Benoit Allard <ben...@gm...> > # Date 1257160071 -3600 > # Node ID bd6b60949b4e68023e41f49ce853c0058e02019b > # Parent 2ff17ece613127b174cb7a6a9aa8ba765ffcbd01 > Remove useless copy operators > > The default one are making the same, and even beter. > Those one were preventing us to subclass the intbv class, as the copy were > forcing the return type to intbv, removing information about our subclass. > > diff -r 2ff17ece6131 -r bd6b60949b4e myhdl/_intbv.py > --- a/myhdl/_intbv.py Tue Oct 06 07:02:37 2009 -0500 > +++ b/myhdl/_intbv.py Mon Nov 02 12:07:51 2009 +0100 > @@ -90,12 +90,6 @@ > def __hash__(self): > raise TypeError("intbv objects are unhashable") > > - # copy methods > - def __copy__(self): > - return intbv(self) > - def __deepcopy__(self, visit): > - return intbv(self) > - > # iterator method > def __iter__(self): > if not self._nrbits: > > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry(R) Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart your > developing skills, take BlackBerry mobile applications to market and stay > ahead of the curve. Join us from November 9 - 12, 2009. Register now! > http://p.sf.net/sfu/devconference > > > ------------------------------------------------------------------------ > > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list -- Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com Python as a HDL: http://www.myhdl.org VHDL development, the modern way: http://www.sigasi.com Analog design automation: http://www.mephisto-da.com World-class digital design: http://www.easics.com |
From: Ben <ben...@gm...> - 2009-11-18 17:53:11
|
Hi Jan, My deep apologies for the delayed answer, I've been diverted by $paying_job. On Wed, Nov 4, 2009 at 12:51, Jan Decaluwe <ja...@ja...> wrote: > I'm not entirely sure I understand the issue, but here are some > upfront remarks. > > Something like a VHDL alias in its full generality would probably > require Python language support. What we can do is try to > accomodate for some limited but interesting cases. > > One issue that I have addressed myself is the fact the MyHDL signal > slices aren't signals. I consider this a major weakness, and I have > come up with a proposal to address what I consider the most important > issues: > > http://www.myhdl.org/doku.php/meps:mep-105 > > An implementation is present in the development trunk. I would be > interested to hear whether this can be a solution for you. E.g: > > class ControlWord(object): > pass > > ctrlword = ControlWord() > > a = intbv(0)[32:] > > ctrlword.subpart = a(4, 2) # shadow signal, only for reading, note round brackets > > Then: with Python you can of course do what you want, very clever > tricks. This is abvolutely fine for modeling. > However, when you also want Verilog/VHDL convertibility, your > options are very limited. E.g. something like the above wouldn't work > because signals as attributes are not yet supported by the convertor. > However, somethink like: > > subpart = a(4, 2) > > would be convertible, because the convertor explicitly supports > dedicated conversion code for shadow signals. > At this point, I'm impressed you found exactly even better than me the origin of my troubles: "slices of Signals aren't Signals". That's to say that I've been reading with great eager your MEP. And that one answers those questions about slicing quite well. But still, i have the impression that the original problem comes from a bit deeper, namely that there is no real combinatorial behavior. I guess you recognized the "<=" in VHDL or the "assign" in verilog. I have the feeling that those ShadowSignal are to fill this gap where asignement is about slicing. All the other one are still there. I always find a bit silly to write a new @always_comb for each MUX for instance. One can argue that it works ... One of my first error messages I got when I was trying MyHDL was something like "A signal is used as inout in a always_comb". First think I did was to improve the error message to identify the signal, and then, split my always_comb (Note to self: think about submitting this patch). MyHDL has its advantages, sure,but I guess after two weeks playing around with it, I can spot its weaknesses. It's a great tool for prototyping, and that's exactly what I did: prototyping. And, last but not least, please correct me if I'm wrong, but it's one of the only simulation solution on MacOSX. And that's greatly appreciated !!! > Finally: the copy methods. I agree that they are not as they should be > as they are not compatible with subclassing now. However, there was a > a reason to have dedicated copy methods instead of the generic ones: > performance. The Signal class is using copy all the time, and it > makes a difference. However, I have to think about it again, because > now that I look at it it may be done much better for the intbv case. > I completely agree, I did some test with my patched version and with you genuine one, the testsuite runs in 14 second without the patch and 19 with it. It's clearly a no-go, I will pop my patch and redefine the copy operators in my subclass. As a side note, I found the DelayedSignal **really** usefull when debugging, I wondered why it wasn't the default, neither documented that much. My patched version has a default delay of 1 ns. And that **greatly** highlight what's going on ... Finally, if you're interrested to look at the project I was/am experimenting with, it can be found there: http://bitbucket.org/benallard/puredarwin You can even add a link from the wiki, if you like, and if my coding style complies with the listed-on-wiki acceptance level ;) Best Regards, Benoit PS: About the wiki, I had the great pleasure to follow the lecture from Jean Demartini (listed on the wiki), but I can't remember anything about MyHDL in there ... I know he refactored his lecture just the year I followed it. Maybe in the past, I can't say ... |
From: Jan D. <ja...@ja...> - 2009-11-20 17:13:26
|
Ben wrote: > But still, i have the impression that the original problem comes from > a bit deeper, namely that there is no real combinatorial behavior. I > guess you recognized the "<=" in VHDL or the "assign" in verilog. I > have the feeling that those ShadowSignal are to fill this gap where > asignement is about slicing. All the other one are still there. I > always find a bit silly to write a new @always_comb for each MUX for > instance. One can argue that it works ... Ok, let's discuss this in detail. Of course there is true combinatorial behavior in MyHDL. With explicit sensitivity lists, you can have it the way you want just like in Verilog or VHDL. I think you mean that there is no implicit combinatorial behavior like with Verilog assign and some concurrent VHDL constructs. It's true that there are no one-liners. However, I think @always_comb comes a long way and is a more general solution. A bit more explicit, but the sensivity list is also inferred implicitly for you. More about it further on. First I'll argue that the problem of signal slices really is different than the continuous assign problem. In Verilog and VHDL, when you slice a signal you get (in some contexts) signal behavior. You don't have to construct any other object explicitly, and you don't need assignments. ShadowSignals are intended to emulate that behavior for them most useful cases. Without them, the overhead to emulate this yourself explicitly is considerable. In comparison, emulating continuous assigns with @always_comb means not much more than some syntax overhead (2 lines). Of course 2 lines is a lot for just a mux. But why indeed would you write a separate @always_comb for each mux? If explicit muxes is what you want, why not use one-liner mux instances? Otherwise, why not put all combinational behavior in one single @always_comb? In MARS.py, you write: @always_comb def updatewe1(): if state == t_State.LOAD: we1_i.next = we1_load else: we1_i.next = we1_proc @always_comb def updateIP1(): if state == t_State.LOAD: IP1_i.next = IP1_load else: IP1_i.next = IP1_proc what I might write as (I like explicit defaults): @always_comb def update(): we1_i.next = we1_proc IP1_i.next = IP1_proc if state == t_State.LOAD: we1_i.next = we1_load P1_i.next = IP1_load I'm a bit surprized that you raise the issue, because on other places in your code you do it already exactly as I suggest. Also, it is clear that your main descriptive tool is the clocked "process", which is my preferred RTL style. In this style, combinatorial processes are the exception. I might e.g. put the output assignments in the example above right in the FSM code itself. Regards, Jan -- Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com Python as a HDL: http://www.myhdl.org VHDL development, the modern way: http://www.sigasi.com Analog design automation: http://www.mephisto-da.com World-class digital design: http://www.easics.com |
From: Benoît <ben...@gm...> - 2009-12-04 17:21:32
|
On 20 nov 2009, at 18:15, Jan Decaluwe <ja...@ja...> wrote: > Ben wrote: > > >> But still, i have the impression that the original problem comes from >> a bit deeper, namely that there is no real combinatorial behavior. I >> guess you recognized the "<=" in VHDL or the "assign" in verilog. I >> have the feeling that those ShadowSignal are to fill this gap where >> asignement is about slicing. All the other one are still there. I >> always find a bit silly to write a new @always_comb for each MUX for >> instance. One can argue that it works ... > > Ok, let's discuss this in detail. > > Of course there is true combinatorial behavior in MyHDL. With > explicit sensitivity lists, you can have it the way you want > just like in Verilog or VHDL. > > I think you mean that there is no implicit combinatorial behavior > like with Verilog assign and some concurrent VHDL constructs. > It's true that there are no one-liners. However, I think @always_comb > comes a long way and is a more general solution. A bit more explicit, > but the sensivity list is also inferred implicitly for you. > More about it further on. > > First I'll argue that the problem of signal slices really is > different than the continuous assign problem. In Verilog and VHDL, > when you slice a signal you get (in some contexts) signal behavior. > You don't have to construct any other object explicitly, and you > don't need assignments. ShadowSignals are intended to emulate that > behavior for them most useful cases. Without them, the overhead > to emulate this yourself explicitly is considerable. > > In comparison, emulating continuous assigns with @always_comb > means not much more than some syntax overhead (2 lines). Of > course 2 lines is a lot for just a mux. But why indeed would > you write a separate @always_comb for each mux? > If explicit muxes is what you want, why not use one-liner > mux instances? Otherwise, why not put all combinational > behavior in one single @always_comb? > > In MARS.py, you write: > > @always_comb > def updatewe1(): > if state == t_State.LOAD: > we1_i.next = we1_load > else: > we1_i.next = we1_proc > > @always_comb > def updateIP1(): > if state == t_State.LOAD: > IP1_i.next = IP1_load > else: > IP1_i.next = IP1_proc > > what I might write as (I like explicit defaults): > > @always_comb > def update(): > we1_i.next = we1_proc > IP1_i.next = IP1_proc > if state == t_State.LOAD: > we1_i.next = we1_load > P1_i.next = IP1_load > > I'm a bit surprized that you raise the issue, because on other > places in your code you do it already exactly as I suggest. > Also, it is clear that your main descriptive tool is the > clocked "process", which is my preferred RTL style. In this > style, combinatorial processes are the exception. I might > e.g. put the output assignments in the example above right in > the FSM code itself. Hi Jan, Of course you are right, thinking about it, I guess the only thing that could justify those statements above is my hardware mind. That same nasty one that makes me think ahead of the cost (latch, wire, clock cycles) of each line I'm writting. That's the way I learnt to write VHDL. Only, this does not apply to MyHDL. This just lead to one question ? How to write MyHDL code ? Depending on what you're looking for I guess. |
From: Jan D. <ja...@ja...> - 2009-12-08 22:14:17
|
Benoît wrote: > Hi Jan, > > Of course you are right, thinking about it, I guess the only thing > that could justify those statements above is my hardware mind. That > same nasty one that makes me think ahead of the cost (latch, wire, > clock cycles) of each line I'm writting. That's the way I learnt to > write VHDL. Only, this does not apply to MyHDL. I think VHDL and MyHDL are much more similar than you suggest here. You could perfectly write MyHDL with the "think hardware" mindset you describe. Personally, I just don't think that "think hardware" is the most effective design strategy. I prefer "synthesis-aware" design where you raise the abstraction level as much as possible without jeopardizing efficiency. You still have to know about hardware, but more importantly, you have to understand what a synthesis tool can and cannot do. Many "hardware thinkers" don't fully appreciate this. They fail to see elegant, efficient solutions, just because they can't visualize them readily in hardware. I have written lots of VHDL since 1990 and I have always used the "synthesis-aware" strategy. So I really don't think it's a matter of HDL language, but of mindset. Of course, some design decision in MyHDL are inspired by my personal preferences, e.g. the intbv class. But I don't think that makes an essential difference here. > This just lead to one question ? How to write MyHDL code ? Depending > on what you're looking for I guess. I do it exactly like I did with VHDL: the highest possible abstraction level, but synthesis-aware. In practice this means e.g. - preference for the clocked process template as a default - no separation between "control" and "data" logic - preference for variables inside processes, including for register inference However, my guess is that many MyHDL users don't do it like that, and MyHDL works for them too. Jan -- Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com Python as a HDL: http://www.myhdl.org VHDL development, the modern way: http://www.sigasi.com Analog design automation: http://www.mephisto-da.com World-class digital design: http://www.easics.com |
From: Felton C. <chr...@gm...> - 2009-12-15 13:23:02
|
Is there any general method for adding error messages? In the MyHDL base there seems to be a couple different methods used? Assertions, Exceptions, prints, etc. I have added some messages over time to my local copy. Some of the messages might be useful to other users as well. Maybe we could add a section on the wiki (maybe under open tasks) that outlines the best approach for adding error, warning, and informative messages. Thanks .chris p.s. sorry if this is a duplicate post, first attempt didn't appear successful. |