[myhdl-list] [PATCH 2 of 2 V3] toVHDL: add support for negative indexes and slice limits
Brought to you by:
jandecaluwe
From: Angel E. <ang...@gm...> - 2012-10-13 22:54:23
|
# HG changeset patch # User Angel Ezquerra <ang...@gm...> # Date 1350086923 -7200 # Branch 0.8-dev # Node ID 2ec0657ef6dbb262b3fc5fed0f9d4f30f82f528b # Parent c641c1ed333d6d03d9cee4a63df5111fe98574c8 toVHDL: add support for negative indexes and slice limits This patch tries to detect negative indexes and slice limits and converts them into indexes or limits relative to the highest bit position on the corresponding bit vector (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. Despite this limitation 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] s_input[-1:-3] = 1 s_input[-8:-14] = 1 else: pass return instances() clk, rst = [Signal(bool()) for n in range(2)] if __name__ == '__main__': sync_inst = toVHDL(test_module3, rst, clk) ~~~ * ISSUES: Mixing negative and positive limits on a single slice does not work fine. The conversion side works ok, but the slice size inference is wrong. diff --git a/myhdl/conversion/_toVHDL.py b/myhdl/conversion/_toVHDL.py --- a/myhdl/conversion/_toVHDL.py +++ b/myhdl/conversion/_toVHDL.py @@ -1241,6 +1241,15 @@ else: self.accessIndex(node) + def _isnegativeindex(self, 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 + def accessSlice(self, node): if isinstance(node.value, ast.Call) and \ node.value.func.obj in (intbv, modbv) and \ @@ -1278,11 +1287,17 @@ if lower is None: self.write("%s" % node.obj._nrbits) else: + if self._isnegativeindex(lower): + # convert negative indexes into indexes from the MSB + self.write('%d + ' % node.value.obj._nrbits) self.visit(lower) self.write("-1 downto ") if upper is None: self.write("0") else: + if self._isnegativeindex(upper): + # convert negative indexes into indexes from the MSB + self.write('%d + ' % node.value.obj._nrbits) self.visit(upper) self.write(")") self.write(suf) @@ -1293,6 +1308,11 @@ self.visit(node.value) self.write("(") #assert len(node.subs) == 1 + + if self._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) |