Re: [myhdl-list] intbv wrap
Brought to you by:
jandecaluwe
From: Christopher F. <chr...@gm...> - 2011-05-05 21:26:08
|
On 5/5/2011 9:21 AM, Ben wrote: > Hi Christopher, > > I took the liberty to review and edit your patch. > > As you can see, I added some tests, and removed the inclusion of the > val property. It became quite smaller ! I left your name in it as the > idea and the logic is from you. > > I also moved the check from the wrap function to the constructor (no > need to check every time.). Perfect! Thanks for the contributions and for the additional test cases, very nice. Also, good catch on the range checking! Is there an opinion if 'myrange' should be a class member so that it doesn't need to be recalculated on each check? I don't know if there is a down side to having too many slots (_range)? In the future we will need to address if wrap() can be converted or changed to a private function? As discussed in previous threads. Thanks again Benoît. Chris > > Here is a text version, enclosed a bundle. All tests pass fine. > > # HG changeset patch > # User cfelton > # Date 1303212809 18000 > # Node ID 145d558e234f363c3e43e9a79ab48ad7e20d7b9b > # Parent f77cf2c4a5894013ceb2f5c184d84136ea4f04a3 > Add a wrap parameter to intbv. When set, no overflow will occur. > > diff -r f77cf2c4a589 -r 145d558e234f myhdl/_intbv.py > --- a/myhdl/_intbv.py Wed May 04 21:33:14 2011 +0200 > +++ b/myhdl/_intbv.py Tue Apr 19 06:33:29 2011 -0500 > @@ -31,37 +31,46 @@ > from __builtin__ import max as maxfunc > > class intbv(object): > - __slots__ = ('_val', '_min', '_max', '_nrbits') > + __slots__ = ('_min', '_max', '_nrbits', '_wrap', '__val') > > - def __init__(self, val=0, min=None, max=None, _nrbits=0): > + def __init__(self, val=0, min=None, max=None, wrap=False, _nrbits=0): > if _nrbits: > self._min = 0 > self._max = 2**_nrbits > + self._nrbits = _nrbits > else: > self._min = min > self._max = max > if max is not None and min is not None: > if min>= 0: > - _nrbits = len(bin(max-1)) > + self._nrbits = len(bin(max-1)) > elif max<= 1: > - _nrbits = len(bin(min)) > + self._nrbits = len(bin(min)) > else: > # make sure there is a leading zero bit in positive numbers > - _nrbits = maxfunc(len(bin(max-1))+1, len(bin(min))) > + self._nrbits = maxfunc(len(bin(max-1))+1, len(bin(min))) > + else: > + self._nrbits = 0 > + > + if wrap: > + myrange = self._nrbits**2 > + if (abs(self.min) != self.max) or ((abs(self.min) + > self.max) != myrange): > + raise ValueError, "Cannot use wrapping if -min != max > (%d != %d)" % (-self.min, self.max) > + self._wrap = wrap > if isinstance(val, (int, long)): > self._val = val > elif isinstance(val, StringType): > mval = val.replace('_', '') > + self._nrbits = len(mval) > self._val = long(mval, 2) > - _nrbits = len(val) > elif isinstance(val, intbv): > self._val = val._val > self._min = val._min > self._max = val._max > - _nrbits = val._nrbits > + self._wrap = val._wrap > + self._nrbits = val._nrbits > else: > raise TypeError("intbv constructor arg should be int or string") > - self._nrbits = _nrbits > self._checkBounds() > > # support for the 'min' and 'max' attribute > @@ -82,6 +91,20 @@ > raise ValueError("intbv value %s< minimum %s" % > (self._val, self._min)) > > + # val property > + def _get_val(self): > + return self.__val > + > + def _set_val(self, pval): > + > + if self._wrap: > + self.__val = self.wrap(pval) > + else: > + self.__val = pval > + > + self._checkBounds() > + > + _val = property(_get_val, _set_val) > > # hash > def __hash__(self): > @@ -433,6 +456,21 @@ > return "intbv(" + repr(self._val) + ")" > > > + def wrap(self, val): > + """ Wrap the value back to the range of the inbv > + > + The following will check that the defined min-max is the full > + range of the binary word. If the full range is specified if > + the value is outside the bounds of the range it will be adjusted > + to the proper value in bounds. > + """ > + myrange = 2**self._nrbits > + > + rval = self.min + ((val +self.max) % myrange) > + > + return rval > + > + > def signed(self): > ''' return integer with the signed value of the intbv instance > > diff -r f77cf2c4a589 -r 145d558e234f myhdl/test/core/test_intbv.py > --- a/myhdl/test/core/test_intbv.py Wed May 04 21:33:14 2011 +0200 > +++ b/myhdl/test/core/test_intbv.py Tue Apr 19 06:33:29 2011 -0500 > @@ -576,8 +576,50 @@ > self.assertEqual(n.max, m.max) > self.assertEqual(len(n), len(m)) > > +class TestIntbvWrap(TestCase): > + > + def testWrap(self): > + x = intbv(0, min=-8, max=8, wrap=True) > + x[:] = x + 1 > + self.assertEqual(1, x) > + x[:] = x + 2 > + self.assertEqual(3, x) > + x[:] = x + 5 > + self.assertEqual(-8, x) > + x[:] = x + 1 > + self.assertEqual(-7, x) > + x[:] = x - 5 > + self.assertEqual(4, x) > + x[:] = x - 4 > + self.assertEqual(0, x) > + x[:] += 15 > + x[:] = x - 1 > + self.assertEqual(-2, x) > + > + def testInit(self): > + self.assertRaises(ValueError, intbv, 15, min=-8, max=8) > + x = intbv(15, min=-8, max=8, wrap=True) > + self.assertEqual(-1, x) > + > + self.assertRaises(ValueError, intbv, 5, min=-3, max=8, wrap=True) > + intbv(5, min=-3, max=8) > > > + def testNoWrap(self): > + x = intbv(0, min=-8, max=8, wrap=False) > + try: > + x[:] += 15 > + self.fail() > + except ValueError: > + pass > + > + x = intbv(0, min=-8, max=8) > + try: > + x[:] += 15 > + self.fail() > + except ValueError: > + pass > + > if __name__ == "__main__": > unittest.main() > > > > ------------------------------------------------------------------------------ > WhatsUp Gold - Download Free Network Management Software > The most intuitive, comprehensive, and cost-effective network > management toolset available today. Delivers lowest initial > acquisition cost and overall TCO of any competing solution. > http://p.sf.net/sfu/whatsupgold-sd > > > > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list |