mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
fhdl: support len() on all values
This commit is contained in:
parent
75d33a0c05
commit
ea63389823
3 changed files with 83 additions and 83 deletions
|
@ -109,6 +109,9 @@ class Value(HUID):
|
||||||
|
|
||||||
def eq(self, r):
|
def eq(self, r):
|
||||||
return _Assign(self, r)
|
return _Assign(self, r)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return value_bits_sign(self)[0]
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return HUID.__hash__(self)
|
return HUID.__hash__(self)
|
||||||
|
@ -164,9 +167,6 @@ class Signal(Value):
|
||||||
self.name_override = name_override
|
self.name_override = name_override
|
||||||
self.backtrace = tracer.trace_back(name)
|
self.backtrace = tracer.trace_back(name)
|
||||||
|
|
||||||
def __len__(self): # TODO: remove (use tools.value_bits_sign instead)
|
|
||||||
return self.nbits
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
|
return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
|
||||||
|
|
||||||
|
@ -299,3 +299,81 @@ class Fragment:
|
||||||
self.specials | other.specials,
|
self.specials | other.specials,
|
||||||
self.clock_domains + other.clock_domains,
|
self.clock_domains + other.clock_domains,
|
||||||
self.sim + other.sim)
|
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
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from migen.fhdl.structure import *
|
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
|
from migen.fhdl.visit import NodeVisitor, NodeTransformer
|
||||||
|
|
||||||
def bitreverse(s):
|
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)]
|
resetcode = [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)]
|
||||||
return [If(rst, *resetcode).Else(*sl)]
|
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
|
# 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.
|
# but can be expressed in terms of other elements (lowered) before conversion.
|
||||||
class _BasicLowerer(NodeTransformer):
|
class _BasicLowerer(NodeTransformer):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
from migen.fhdl.specials import Special
|
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:
|
class MultiRegImpl:
|
||||||
def __init__(self, i, o, odomain, n):
|
def __init__(self, i, o, odomain, n):
|
||||||
|
|
Loading…
Reference in a new issue