From: Robert Jordens Date: Tue, 3 Dec 2013 21:12:40 +0000 (-0700) Subject: fhdl.size: rename to bitcontainer X-Git-Tag: 24jan2021_ls180~2099^2~402 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8d3d61ba9840ddbf6424a368aaab86e678404078;p=litex.git fhdl.size: rename to bitcontainer --- diff --git a/doc/api.rst b/doc/api.rst index d49b9b70..1181773c 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -8,10 +8,10 @@ migen API Documentation :members: :show-inheritance: -:mod:`fhdl.size` Module +:mod:`fhdl.bitcontainer` Module ------------------------------ -.. automodule:: migen.fhdl.size +.. automodule:: migen.fhdl.bitcontainer :members: :show-inheritance: diff --git a/migen/fhdl/bitcontainer.py b/migen/fhdl/bitcontainer.py new file mode 100644 index 00000000..345c9c54 --- /dev/null +++ b/migen/fhdl/bitcontainer.py @@ -0,0 +1,202 @@ +from migen.fhdl import structure as f + +def log2_int(n, need_pow2=True): + l = 1 + r = 0 + while l < n: + l *= 2 + r += 1 + if need_pow2 and l != n: + raise ValueError("Not a power of 2") + return r + +def bits_for(n, require_sign_bit=False): + if n > 0: + r = log2_int(n + 1, False) + else: + require_sign_bit = True + r = log2_int(-n, False) + if require_sign_bit: + r += 1 + return r + +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, f.Signal): + return v.nbits, v.signed + elif isinstance(v, (f.ClockSignal, f.ResetSignal)): + return 1, False + elif isinstance(v, f._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, f._Slice): + return v.stop - v.start, value_bits_sign(v.value)[1] + elif isinstance(v, f.Cat): + return sum(value_bits_sign(sv)[0] for sv in v.l), False + elif isinstance(v, f.Replicate): + return (value_bits_sign(v.v)[0])*v.n, False + elif isinstance(v, f._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("Can not calculate bit length of {} {}".format( + type(v), v)) + +def flen(v): + """Bit length of an expression + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + int + Number of bits required to store `v` or available in `v` + + Examples + -------- + >>> flen(f.Signal(8)) + 8 + >>> flen(0xaa) + 8 + """ + return value_bits_sign(v)[0] + +def fiter(v): + """Bit iterator + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + iter + Iterator over the bits in `v` + + Examples + -------- + >>> list(fiter(f.Signal(2))) #doctest: +ELLIPSIS + [, ] + >>> list(fiter(4)) + [0, 0, 1] + """ + if isinstance(v, (bool, int)): + return ((v >> i) & 1 for i in range(bits_for(v))) + elif isinstance(v, f.Value): + return (v[i] for i in range(flen(v))) + else: + raise TypeError("Can not bit-iterate {} {}".format(type(v), v)) + +def fslice(v, s): + """Bit slice + + Parameters + ---------- + v : int, bool or Value + s : slice or int + + Returns + ------- + int or Value + Expression for the slice `s` of `v`. + + Examples + -------- + >>> fslice(f.Signal(2), 1) #doctest: +ELLIPSIS + + >>> bin(fslice(0b1101, slice(1, None, 2))) + '0b10' + >>> fslice(-1, slice(0, 4)) + 1 + >>> fslice(-7, slice(None)) + 9 + """ + if isinstance(v, (bool, int)): + if isinstance(s, int): + s = slice(s) + idx = range(*s.indices(bits_for(v))) + return sum(((v >> i) & 1) << j for j, i in enumerate(idx)) + elif isinstance(v, f.Value): + return v[s] + else: + raise TypeError("Can not bit-slice {} {}".format(type(v), v)) + +def freversed(v): + """Bit reverse + + Parameters + ---------- + v : int, bool or Value + + Returns + ------- + int or Value + Expression containing the bit reversed input. + + Examples + -------- + >>> freversed(f.Signal(2)) #doctest: +ELLIPSIS + + >>> bin(freversed(0b1011)) + '0b1101' + """ + return fslice(v, slice(None, None, -1)) diff --git a/migen/fhdl/size.py b/migen/fhdl/size.py deleted file mode 100644 index 345c9c54..00000000 --- a/migen/fhdl/size.py +++ /dev/null @@ -1,202 +0,0 @@ -from migen.fhdl import structure as f - -def log2_int(n, need_pow2=True): - l = 1 - r = 0 - while l < n: - l *= 2 - r += 1 - if need_pow2 and l != n: - raise ValueError("Not a power of 2") - return r - -def bits_for(n, require_sign_bit=False): - if n > 0: - r = log2_int(n + 1, False) - else: - require_sign_bit = True - r = log2_int(-n, False) - if require_sign_bit: - r += 1 - return r - -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, f.Signal): - return v.nbits, v.signed - elif isinstance(v, (f.ClockSignal, f.ResetSignal)): - return 1, False - elif isinstance(v, f._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, f._Slice): - return v.stop - v.start, value_bits_sign(v.value)[1] - elif isinstance(v, f.Cat): - return sum(value_bits_sign(sv)[0] for sv in v.l), False - elif isinstance(v, f.Replicate): - return (value_bits_sign(v.v)[0])*v.n, False - elif isinstance(v, f._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("Can not calculate bit length of {} {}".format( - type(v), v)) - -def flen(v): - """Bit length of an expression - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - int - Number of bits required to store `v` or available in `v` - - Examples - -------- - >>> flen(f.Signal(8)) - 8 - >>> flen(0xaa) - 8 - """ - return value_bits_sign(v)[0] - -def fiter(v): - """Bit iterator - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - iter - Iterator over the bits in `v` - - Examples - -------- - >>> list(fiter(f.Signal(2))) #doctest: +ELLIPSIS - [, ] - >>> list(fiter(4)) - [0, 0, 1] - """ - if isinstance(v, (bool, int)): - return ((v >> i) & 1 for i in range(bits_for(v))) - elif isinstance(v, f.Value): - return (v[i] for i in range(flen(v))) - else: - raise TypeError("Can not bit-iterate {} {}".format(type(v), v)) - -def fslice(v, s): - """Bit slice - - Parameters - ---------- - v : int, bool or Value - s : slice or int - - Returns - ------- - int or Value - Expression for the slice `s` of `v`. - - Examples - -------- - >>> fslice(f.Signal(2), 1) #doctest: +ELLIPSIS - - >>> bin(fslice(0b1101, slice(1, None, 2))) - '0b10' - >>> fslice(-1, slice(0, 4)) - 1 - >>> fslice(-7, slice(None)) - 9 - """ - if isinstance(v, (bool, int)): - if isinstance(s, int): - s = slice(s) - idx = range(*s.indices(bits_for(v))) - return sum(((v >> i) & 1) << j for j, i in enumerate(idx)) - elif isinstance(v, f.Value): - return v[s] - else: - raise TypeError("Can not bit-slice {} {}".format(type(v), v)) - -def freversed(v): - """Bit reverse - - Parameters - ---------- - v : int, bool or Value - - Returns - ------- - int or Value - Expression containing the bit reversed input. - - Examples - -------- - >>> freversed(f.Signal(2)) #doctest: +ELLIPSIS - - >>> bin(freversed(0b1011)) - '0b1101' - """ - return fslice(v, slice(None, None, -1)) diff --git a/migen/fhdl/specials.py b/migen/fhdl/specials.py index ad11f578..ae0a2e63 100644 --- a/migen/fhdl/specials.py +++ b/migen/fhdl/specials.py @@ -1,7 +1,7 @@ from operator import itemgetter from migen.fhdl.structure import * -from migen.fhdl.size import bits_for, value_bits_sign +from migen.fhdl.bitcontainer import bits_for, value_bits_sign from migen.fhdl.tools import * from migen.fhdl.tracer import get_obj_var_name from migen.fhdl.verilog import _printexpr as verilog_printexpr diff --git a/migen/fhdl/std.py b/migen/fhdl/std.py index b9ec729f..2007ff3f 100644 --- a/migen/fhdl/std.py +++ b/migen/fhdl/std.py @@ -1,5 +1,5 @@ from migen.fhdl.structure import * from migen.fhdl.module import Module from migen.fhdl.specials import TSTriple, Instance, Memory -from migen.fhdl.size import log2_int, bits_for, flen, fiter, fslice, freversed +from migen.fhdl.bitcontainer import log2_int, bits_for, flen, fiter, fslice, freversed from migen.fhdl.decorators import DecorateModule, InsertCE, InsertReset, RenameClockDomains diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py index aba747b3..9b31e696 100644 --- a/migen/fhdl/structure.py +++ b/migen/fhdl/structure.py @@ -79,7 +79,7 @@ class Value(HUID): def __getitem__(self, key): - from migen.fhdl.size import flen + from migen.fhdl.bitcontainer import flen if isinstance(key, int): if key < 0: @@ -242,7 +242,7 @@ class Signal(Value): related : Signal or None """ def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None): - from migen.fhdl.size import bits_for + from migen.fhdl.bitcontainer import bits_for Value.__init__(self) diff --git a/migen/fhdl/tools.py b/migen/fhdl/tools.py index b25280ba..00c9932f 100644 --- a/migen/fhdl/tools.py +++ b/migen/fhdl/tools.py @@ -1,7 +1,7 @@ from migen.fhdl.structure import * from migen.fhdl.structure import _Slice, _Assign from migen.fhdl.visit import NodeVisitor, NodeTransformer -from migen.fhdl.size import value_bits_sign +from migen.fhdl.bitcontainer import value_bits_sign from migen.util.misc import flat_iteration class _SignalLister(NodeVisitor): diff --git a/migen/fhdl/verilog.py b/migen/fhdl/verilog.py index 10bd7e37..fc56f784 100644 --- a/migen/fhdl/verilog.py +++ b/migen/fhdl/verilog.py @@ -4,7 +4,7 @@ from operator import itemgetter from migen.fhdl.structure import * from migen.fhdl.structure import _Operator, _Slice, _Assign, _Fragment from migen.fhdl.tools import * -from migen.fhdl.size import bits_for, flen +from migen.fhdl.bitcontainer import bits_for, flen from migen.fhdl.namer import Namespace, build_namespace def _printsig(ns, s): diff --git a/migen/genlib/cdc.py b/migen/genlib/cdc.py index 773c7b2c..9cdca4ab 100644 --- a/migen/genlib/cdc.py +++ b/migen/genlib/cdc.py @@ -1,5 +1,5 @@ from migen.fhdl.std import * -from migen.fhdl.size import value_bits_sign +from migen.fhdl.bitcontainer import value_bits_sign from migen.fhdl.specials import Special from migen.fhdl.tools import list_signals