fhdl: support len() on all values
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 14 Apr 2013 11:50:26 +0000 (13:50 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 14 Apr 2013 11:50:26 +0000 (13:50 +0200)
migen/fhdl/structure.py
migen/fhdl/tools.py
migen/genlib/cdc.py

index 08747359399f4eb61f67fc4d6c2faf0575e808ea..355713c7601e17847f975bc0f53d1dcc8454429e 100644 (file)
@@ -109,6 +109,9 @@ class Value(HUID):
        
        def eq(self, r):
                return _Assign(self, r)
+
+       def __len__(self):
+               return value_bits_sign(self)[0]
        
        def __hash__(self):
                return HUID.__hash__(self)
@@ -164,9 +167,6 @@ class Signal(Value):
                self.name_override = name_override
                self.backtrace = tracer.trace_back(name)
 
-       def __len__(self): # TODO: remove (use tools.value_bits_sign instead)
-               return self.nbits
-
        def __repr__(self):
                return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
 
@@ -299,3 +299,81 @@ class Fragment:
                        self.specials | other.specials,
                        self.clock_domains + other.clock_domains,
                        self.sim + other.sim)
+
+def value_bits_sign(v):
+       if isinstance(v, bool):
+               return 1, False
+       elif isinstance(v, int):
+               return bits_for(v), v < 0
+       elif isinstance(v, Signal):
+               return v.nbits, v.signed
+       elif isinstance(v, (ClockSignal, ResetSignal)):
+               return 1, False
+       elif isinstance(v, _Operator):
+               obs = list(map(value_bits_sign, v.operands))
+               if v.op == "+" or v.op == "-":
+                       if not obs[0][1] and not obs[1][1]:
+                               # both operands unsigned
+                               return max(obs[0][0], obs[1][0]) + 1, False
+                       elif obs[0][1] and obs[1][1]:
+                               # both operands signed
+                               return max(obs[0][0], obs[1][0]) + 1, True
+                       elif not obs[0][1] and obs[1][1]:
+                               # first operand unsigned (add sign bit), second operand signed
+                               return max(obs[0][0] + 1, obs[1][0]) + 1, True
+                       else:
+                               # first signed, second operand unsigned (add sign bit)
+                               return max(obs[0][0], obs[1][0] + 1) + 1, True
+               elif v.op == "*":
+                       if not obs[0][1] and not obs[1][1]:
+                               # both operands unsigned
+                               return obs[0][0] + obs[1][0]
+                       elif obs[0][1] and obs[1][1]:
+                               # both operands signed
+                               return obs[0][0] + obs[1][0] - 1
+                       else:
+                               # one operand signed, the other unsigned (add sign bit)
+                               return obs[0][0] + obs[1][0] + 1 - 1
+               elif v.op == "<<<":
+                       if obs[1][1]:
+                               extra = 2**(obs[1][0] - 1) - 1
+                       else:
+                               extra = 2**obs[1][0] - 1
+                       return obs[0][0] + extra, obs[0][1]
+               elif v.op == ">>>":
+                       if obs[1][1]:
+                               extra = 2**(obs[1][0] - 1)
+                       else:
+                               extra = 0
+                       return obs[0][0] + extra, obs[0][1]
+               elif v.op == "&" or v.op == "^" or v.op == "|":
+                       if not obs[0][1] and not obs[1][1]:
+                               # both operands unsigned
+                               return max(obs[0][0], obs[1][0]), False
+                       elif obs[0][1] and obs[1][1]:
+                               # both operands signed
+                               return max(obs[0][0], obs[1][0]), True
+                       elif not obs[0][1] and obs[1][1]:
+                               # first operand unsigned (add sign bit), second operand signed
+                               return max(obs[0][0] + 1, obs[1][0]), True
+                       else:
+                               # first signed, second operand unsigned (add sign bit)
+                               return max(obs[0][0], obs[1][0] + 1), True
+               elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \
+                 or v.op == ">" or v.op == ">=":
+                         return 1, False
+               elif v.op == "~":
+                       return obs[0]
+               else:
+                       raise TypeError
+       elif isinstance(v, _Slice):
+               return v.stop - v.start, value_bits_sign(v.value)[1]
+       elif isinstance(v, Cat):
+               return sum(value_bits_sign(sv)[0] for sv in v.l), False
+       elif isinstance(v, Replicate):
+               return (value_bits_sign(v.v)[0])*v.n, False
+       elif isinstance(v, _ArrayProxy):
+               bsc = map(value_bits_sign, v.choices)
+               return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc)
+       else:
+               raise TypeError
index 80dda17134d81461586683bf337d3cc2ed2e2835..7c556f8b92bc364a2e3596a2ca6b1162cdc8d6e4 100644 (file)
@@ -1,7 +1,7 @@
 import collections
 
 from migen.fhdl.structure import *
-from migen.fhdl.structure import _Operator, _Slice, _Assign, _ArrayProxy
+from migen.fhdl.structure import _Slice, _Assign
 from migen.fhdl.visit import NodeVisitor, NodeTransformer
 
 def bitreverse(s):
@@ -117,84 +117,6 @@ def insert_reset(rst, sl):
        resetcode = [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)]
        return [If(rst, *resetcode).Else(*sl)]
 
-def value_bits_sign(v):
-       if isinstance(v, bool):
-               return 1, False
-       elif isinstance(v, int):
-               return bits_for(v), v < 0
-       elif isinstance(v, Signal):
-               return v.nbits, v.signed
-       elif isinstance(v, (ClockSignal, ResetSignal)):
-               return 1, False
-       elif isinstance(v, _Operator):
-               obs = list(map(value_bits_sign, v.operands))
-               if v.op == "+" or v.op == "-":
-                       if not obs[0][1] and not obs[1][1]:
-                               # both operands unsigned
-                               return max(obs[0][0], obs[1][0]) + 1, False
-                       elif obs[0][1] and obs[1][1]:
-                               # both operands signed
-                               return max(obs[0][0], obs[1][0]) + 1, True
-                       elif not obs[0][1] and obs[1][1]:
-                               # first operand unsigned (add sign bit), second operand signed
-                               return max(obs[0][0] + 1, obs[1][0]) + 1, True
-                       else:
-                               # first signed, second operand unsigned (add sign bit)
-                               return max(obs[0][0], obs[1][0] + 1) + 1, True
-               elif v.op == "*":
-                       if not obs[0][1] and not obs[1][1]:
-                               # both operands unsigned
-                               return obs[0][0] + obs[1][0]
-                       elif obs[0][1] and obs[1][1]:
-                               # both operands signed
-                               return obs[0][0] + obs[1][0] - 1
-                       else:
-                               # one operand signed, the other unsigned (add sign bit)
-                               return obs[0][0] + obs[1][0] + 1 - 1
-               elif v.op == "<<<":
-                       if obs[1][1]:
-                               extra = 2**(obs[1][0] - 1) - 1
-                       else:
-                               extra = 2**obs[1][0] - 1
-                       return obs[0][0] + extra, obs[0][1]
-               elif v.op == ">>>":
-                       if obs[1][1]:
-                               extra = 2**(obs[1][0] - 1)
-                       else:
-                               extra = 0
-                       return obs[0][0] + extra, obs[0][1]
-               elif v.op == "&" or v.op == "^" or v.op == "|":
-                       if not obs[0][1] and not obs[1][1]:
-                               # both operands unsigned
-                               return max(obs[0][0], obs[1][0]), False
-                       elif obs[0][1] and obs[1][1]:
-                               # both operands signed
-                               return max(obs[0][0], obs[1][0]), True
-                       elif not obs[0][1] and obs[1][1]:
-                               # first operand unsigned (add sign bit), second operand signed
-                               return max(obs[0][0] + 1, obs[1][0]), True
-                       else:
-                               # first signed, second operand unsigned (add sign bit)
-                               return max(obs[0][0], obs[1][0] + 1), True
-               elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \
-                 or v.op == ">" or v.op == ">=":
-                         return 1, False
-               elif v.op == "~":
-                       return obs[0]
-               else:
-                       raise TypeError
-       elif isinstance(v, _Slice):
-               return v.stop - v.start, value_bits_sign(v.value)[1]
-       elif isinstance(v, Cat):
-               return sum(value_bits_sign(sv)[0] for sv in v.l), False
-       elif isinstance(v, Replicate):
-               return (value_bits_sign(v.v)[0])*v.n, False
-       elif isinstance(v, _ArrayProxy):
-               bsc = map(value_bits_sign, v.choices)
-               return max(bs[0] for bs in bsc), any(bs[1] for bs in bsc)
-       else:
-               raise TypeError
-
 # Basics are FHDL structure elements that back-ends are not required to support
 # but can be expressed in terms of other elements (lowered) before conversion.
 class _BasicLowerer(NodeTransformer):
index 7aff864d5fa354b1c1f476cb2f75c4784db47560..04b1b8500977869eb5ed5c512ecc5d7f8b6d64e6 100644 (file)
@@ -1,6 +1,6 @@
 from migen.fhdl.structure import *
 from migen.fhdl.specials import Special
-from migen.fhdl.tools import value_bits_sign, list_signals
+from migen.fhdl.tools import list_signals
 
 class MultiRegImpl:
        def __init__(self, i, o, odomain, n):