Thread: [myhdl-list] [PATCH 0 of 2 V2] Add support for negative indexes
Brought to you by:
jandecaluwe
From: Angel E. <ang...@gm...> - 2012-10-13 16:33:04
|
This is a second, cleaner and more complete version of this patch series. The first patch has not changed compared to the previous version of this patch series. On the other hand, the second patch should work much better, and should support both negative numbers as indexes and explicit negative operations through the negative unary operation. |
From: Angel E. <ang...@gm...> - 2012-10-13 00:12:12
|
Python lists have a natural way to access list itemps from the end of the list, which is to use negative indexes. These patches add this functionality to MyHDL. The first patch adds negative index and slice limit support to the intbv class. I think this first patch is probably right and not very controversial (although I might be totally wrong, since this is my first attempt at making a serious modification to MyHDL). The second patch is _very_ rough and probably breaks lots of things. It adds support for negative indexes (not slices) to the VHDL convertor. I'd really appreaciate any help with improving this patch in particular. Comments are welcome! |
From: Angel E. <ang...@gm...> - 2012-10-13 00:12:13
Attachments:
myhdl-1.patch
|
# HG changeset patch # User Angel Ezquerra <ang...@gm...> # Date 1350077846 -7200 # Branch 0.8-dev # Node ID c641c1ed333d6d03d9cee4a63df5111fe98574c8 # Parent 6f6571dbd495f197531f0406763ff10e4ce3b3ee intbv: add support for negative indexes and slice limits Negative indexes are supported on regular python lists. They are very useful when you want to refer to a position from the end of the list. This same concept can be applied to intbv indexes and slices. Supporting negative indexes reduces the need to use the len() function to calculate a position from the MSB of the intbv. Note that converting negative indexes is not supported yet. diff --git a/myhdl/_intbv.py b/myhdl/_intbv.py --- a/myhdl/_intbv.py +++ b/myhdl/_intbv.py @@ -127,11 +127,15 @@ j = 0 j = int(j) if j < 0: - raise ValueError, "intbv[i:j] requires j >= 0\n" \ - " j == %s" % j + j = self._nrbits + j + if j < 0: + raise ValueError, "intbv[i:j] requires j >= 0\n" \ + " j == %s" % j if i is None: # default return type(self)(self._val >> j) i = int(i) + if i < 0: + i = self._nrbits + i if i <= j: raise ValueError, "intbv[i:j] requires i > j\n" \ " i, j == %s, %s" % (i, j) @@ -139,6 +143,8 @@ return res else: i = int(key) + if i < 0: + i = self._nrbits + i res = bool((self._val >> i) & 0x1) return res @@ -153,14 +159,18 @@ j = 0 j = int(j) if j < 0: - raise ValueError, "intbv[i:j] = v requires j >= 0\n" \ - " j == %s" % j + j = self._nrbits + j + if j < 0: + raise ValueError, "intbv[i:j] = v requires j >= 0\n" \ + " j == %s" % j if i is None: # default q = self._val % (1L << j) self._val = val * (1L << j) + q self._handleBounds() return i = int(i) + if i < 0: + i = self._nrbits + i if i <= j: raise ValueError, "intbv[i:j] = v requires i > j\n" \ " i, j, v == %s, %s, %s" % (i, j, val) @@ -174,6 +184,8 @@ self._handleBounds() else: i = int(key) + if i < 0: + i = self._nrbits + i if val == 1: self._val |= (1L << i) elif val == 0: |
From: Angel E. <ang...@gm...> - 2012-10-13 00:12:13
Attachments:
myhdl-2.patch
|
# HG changeset patch # User Angel Ezquerra <ang...@gm...> # Date 1350086923 -7200 # Branch 0.8-dev # Node ID 1a024c51a10d48b9de7e5d0d3886e3498c4dcfbb # Parent c641c1ed333d6d03d9cee4a63df5111fe98574c8 toVHDL: add support for negative indexes This is _very_ rough. This patch tries to detect negative indexes and converts them into indexes relative to the highest bit position (with -1 corresponding to the highest bit). This probably breaks all sorts of things since it does not check if the index is an integer or not, and the way it updates the slice node is probably wrong as well. However, the following simple test case converts fine with this patch: ~~~ #!/usr/env python from myhdl import * def test_module(rst, clk): '''This block generates the radio frame synchronization signal''' s_output = Signal(intbv(0)[16:]) s_input = Signal(intbv(0)[16:]) @always(clk.posedge, rst.posedge) def p_process(): if rst == 1: s_input[-1] = 1 s_output.next = s_input else: pass return instances() clk, rst = [Signal(bool()) for n in range(2)] if __name__ == '__main__': sync_inst = toVHDL(test_module3, rst, clk) ~~~ diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -1293,6 +1293,12 @@ self.visit(node.value) self.write("(") #assert len(node.subs) == 1 + if node.slice.value.value < 0: + # convert negative indexes into indexes from the MSB + newindex = node.value.obj._nrbits + node.slice.value.value + node.slice.value = newindex + node.slice.value.n = newindex + node.slice.value.value = newindex self.visit(node.slice.value) self.write(")") self.write(suf) |
From: Jan D. <ja...@ja...> - 2013-09-09 08:11:24
|
On 10/13/2012 02:12 AM, Angel Ezquerra wrote: > Python lists have a natural way to access list itemps from the end of > the list, which is to use negative indexes. These patches add this > functionality to MyHDL. > > The first patch adds negative index and slice limit support to the > intbv class. I think this first patch is probably right and not very > controversial intbv's are dual in nature - bit sequence but also integer interpretation. indexing is at the intersection of the two. An index corresponds to a bit position, but also to the power of the bit when expanding the integer in a sum of powers of 2. To match the natural way of writing numbers, intbv slicing is already totally different from any standard python sequence: the direction is reversed. Personally, I haven't seen much need to enhance intbv bit indexing to match what you can do with sequences like lists. However, there is a very good reason to stress the power of two interpretation: when we add a fixbv type, it would be natural to use the same interpretation. Negative indices would represent fractional bits. It also seems natural that the intbv would like a subtype of a general fixbv type. Therefore, I propose to keep intbv indexing like it is. -- 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 World-class digital design: http://www.easics.com |
From: Angel E. <ang...@gm...> - 2013-09-28 08:34:44
|
On Mon, Sep 9, 2013 at 10:11 AM, Jan Decaluwe <ja...@ja...> wrote: > On 10/13/2012 02:12 AM, Angel Ezquerra wrote: >> Python lists have a natural way to access list itemps from the end of >> the list, which is to use negative indexes. These patches add this >> functionality to MyHDL. >> >> The first patch adds negative index and slice limit support to the >> intbv class. I think this first patch is probably right and not very >> controversial > > intbv's are dual in nature - bit sequence but also integer interpretation. > > indexing is at the intersection of the two. An index corresponds > to a bit position, but also to the power of the bit when > expanding the integer in a sum of powers of 2. To match > the natural way of writing numbers, intbv slicing is already > totally different from any standard python sequence: the direction > is reversed. > > Personally, I haven't seen much need to enhance intbv bit indexing > to match what you can do with sequences like lists. However, there > is a very good reason to stress the power of two interpretation: > when we add a fixbv type, it would be natural to use the same > interpretation. Negative indices would represent fractional bits. > It also seems natural that the intbv would like a subtype of > a general fixbv type. > > Therefore, I propose to keep intbv indexing like it is. Jan, sorry it took me a while to get the time to respond. I understand your point that it would be useful to use negative indexes to indicate fractional bits on a fixbv. However in my experience I am as likely to need to access bits from the LSB than from the MSB. I often see VHDL code that needs to do an explicit mathematical operation to access the 2nd leftmost bit in a std_logic_vector, for example. I find it silly that you have to care about such a thing, when the synthesizer can do that calculation for you. To me this is a very clear example of a way in which a python based HDL can extend the capabilities of regular HDL syntax, making what is unnecessarily hard on VHDL or Verilog easy and concise. Thus I still believe that it would be very useful to be able to refer to bits from the MSB. The fixbv class will be useful, no doubt, but there is a lot of code that will keep using regular intbv. I don't think the capabilities of the intbv class should be limited because they could interfere with a derived class which is not even finished yet. That being said perhaps there is a way to keep negative index bit access while retaining the capability of accessing fractional fixbv bits. The trick is to think of the negative index access as a modulo operation on the length of the bit vector. That is: actual_index = index % vector_length In the case of a fixbv this could be extended by taking into account the position of the fractional "dot" on the vector as follows: actual_index = (index + dot_position) % vector_length Of course we could just disallow going beyond the limit in the fixbv case, but the definition would be the same in both classes. Cheers, Angel |
From: Jan D. <ja...@ja...> - 2013-09-09 08:37:26
|
On 10/13/2012 02:12 AM, Angel Ezquerra wrote: > Python lists have a natural way to access list itemps from the end of > the list, which is to use negative indexes. These patches add this > functionality to MyHDL. > > The first patch adds negative index and slice limit support to the > intbv class. I think this first patch is probably right and not very > controversial intbv's are dual in nature - bit sequence but also integer interpretation. indexing is at the intersection of the two. An index corresponds to a bit position, but also to the power of the bit when expanding the integer in a sum of powers of 2. To match the natural way of writing numbers, intbv slicing is already totally different from any standard python sequence: the direction is reversed. Personally, I haven't seen much need to enhance intbv bit indexing to match what you can do with sequences like lists. However, there is a very good reason to stress the power of two interpretation: when we add a fixbv type, it would be natural to use the same interpretation. Negative indices would represent fractional bits. It also seems natural that the intbv would like a subtype of a general fixbv type. Therefore, I propose to keep intbv indexing like it is. -- 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 World-class digital design: http://www.easics.com |
From: Jan D. <ja...@ja...> - 2013-09-09 08:43:37
|
On 10/13/2012 02:12 AM, Angel Ezquerra wrote: > Python lists have a natural way to access list itemps from the end of > the list, which is to use negative indexes. These patches add this > functionality to MyHDL. > > The first patch adds negative index and slice limit support to the > intbv class. I think this first patch is probably right and not very > controversial intbv's are dual in nature - bit sequence but also integer interpretation. indexing is at the intersection of the two. An index corresponds to a bit position, but also to the power of the bit when expanding the integer in a sum of powers of 2. To match the natural way of writing numbers, intbv slicing is already totally different from any standard python sequence: the direction is reversed. Personally, I haven't seen much need to enhance intbv bit indexing to match what you can do with sequences like lists. However, there is a very good reason to stress the power of two interpretation: when we add a fixbv type, it would be natural to use the same interpretation. Negative indices would represent fractional bits. It also seems natural that the intbv would like a subtype of a general fixbv type. Therefore, I propose to keep intbv indexing like it is. -- 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 World-class digital design: http://www.easics.com |
From: Angel E. <ang...@gm...> - 2012-10-13 16:33:05
Attachments:
myhdl-1.patch
|
# HG changeset patch # User Angel Ezquerra <ang...@gm...> # Date 1350077846 -7200 # Branch 0.8-dev # Node ID c641c1ed333d6d03d9cee4a63df5111fe98574c8 # Parent 6f6571dbd495f197531f0406763ff10e4ce3b3ee intbv: add support for negative indexes and slice limits Negative indexes are supported on regular python lists. They are very useful when you want to refer to a position from the end of the list. This same concept can be applied to intbv indexes and slices. Supporting negative indexes reduces the need to use the len() function to calculate a position from the MSB of the intbv. Note that converting negative indexes is not supported yet. diff --git a/myhdl/_intbv.py b/myhdl/_intbv.py --- a/myhdl/_intbv.py +++ b/myhdl/_intbv.py @@ -127,11 +127,15 @@ j = 0 j = int(j) if j < 0: - raise ValueError, "intbv[i:j] requires j >= 0\n" \ - " j == %s" % j + j = self._nrbits + j + if j < 0: + raise ValueError, "intbv[i:j] requires j >= 0\n" \ + " j == %s" % j if i is None: # default return type(self)(self._val >> j) i = int(i) + if i < 0: + i = self._nrbits + i if i <= j: raise ValueError, "intbv[i:j] requires i > j\n" \ " i, j == %s, %s" % (i, j) @@ -139,6 +143,8 @@ return res else: i = int(key) + if i < 0: + i = self._nrbits + i res = bool((self._val >> i) & 0x1) return res @@ -153,14 +159,18 @@ j = 0 j = int(j) if j < 0: - raise ValueError, "intbv[i:j] = v requires j >= 0\n" \ - " j == %s" % j + j = self._nrbits + j + if j < 0: + raise ValueError, "intbv[i:j] = v requires j >= 0\n" \ + " j == %s" % j if i is None: # default q = self._val % (1L << j) self._val = val * (1L << j) + q self._handleBounds() return i = int(i) + if i < 0: + i = self._nrbits + i if i <= j: raise ValueError, "intbv[i:j] = v requires i > j\n" \ " i, j, v == %s, %s, %s" % (i, j, val) @@ -174,6 +184,8 @@ self._handleBounds() else: i = int(key) + if i < 0: + i = self._nrbits + i if val == 1: self._val |= (1L << i) elif val == 0: |
From: Angel E. <ang...@gm...> - 2012-10-13 16:33:06
Attachments:
myhdl-2.patch
|
# HG changeset patch # User Angel Ezquerra <ang...@gm...> # Date 1350086923 -7200 # Branch 0.8-dev # Node ID b8fa9fcfe7f2f4712c64b98da346191f57fef193 # Parent c641c1ed333d6d03d9cee4a63df5111fe98574c8 toVHDL: add support for negative indexes This patch tries to detect negative indexes and converts them into indexes relative to the highest bit position (with -1 corresponding to the highest bit). This is similar to what Python does with negative indexes for regular lists. Two types of "negative indexes" are supported with this patch: - Explicit negative numbers (e.g. -1, -3, etc) - Explicit negative unary operator surrounding any other operation (e.g. -(2 * 3)) Other cases in which the index may be negative are not detected. Negative indexes are not supported for slices either (yet), just for simple one bit index accesses. Despite these limitations I think that this functionality can be quite useful. As an example, the following simple test case converts fine with this patch: ~~~ #!/usr/env python from myhdl import * def test_module(rst, clk): '''This block generates the radio frame synchronization signal''' s_output = Signal(intbv(0)[16:]) s_input = Signal(intbv(0)[16:]) @always(clk.posedge, rst.posedge) def p_process(): if rst == 1: s_input[-1] = 1 s_input[-(3*2)] = 1 s_output.next[-2] = s_input[-3] else: pass return instances() clk, rst = [Signal(bool()) for n in range(2)] if __name__ == '__main__': sync_inst = toVHDL(test_module3, rst, clk) ~~~ diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -1293,6 +1293,19 @@ self.visit(node.value) self.write("(") #assert len(node.subs) == 1 + + def isnegativeindex(astvalue): + if isinstance(astvalue, ast.Num): + if astvalue.value < 0: + return True + elif isinstance(astvalue, ast.UnaryOp): + if isinstance(astvalue.op, ast.USub): + return True + return False + if isnegativeindex(node.slice.value): + # convert negative indexes into indexes from the MSB + self.write('%d + ' % node.value.obj._nrbits) + self.visit(node.slice.value) self.write(")") self.write(suf) |