compat: add wrappers for Slice.stop, Cat.l, _ArrayProxy.choices.
[nmigen.git] / nmigen / tools.py
1 from collections.abc import Iterable
2 import functools
3 import warnings
4
5
6 __all__ = ["flatten", "union", "log2_int", "bits_for", "deprecated"]
7
8
9 def flatten(i):
10 for e in i:
11 if isinstance(e, Iterable):
12 yield from flatten(e)
13 else:
14 yield e
15
16
17 def union(i, start=None):
18 r = start
19 for e in i:
20 if r is None:
21 r = e
22 else:
23 r |= e
24 return r
25
26
27 def log2_int(n, need_pow2=True):
28 if n == 0:
29 return 0
30 r = (n - 1).bit_length()
31 if need_pow2 and (1 << r) != n:
32 raise ValueError("{} is not a power of 2".format(n))
33 return r
34
35
36 def bits_for(n, require_sign_bit=False):
37 if n > 0:
38 r = log2_int(n + 1, False)
39 else:
40 require_sign_bit = True
41 r = log2_int(-n, False)
42 if require_sign_bit:
43 r += 1
44 return r
45
46
47 def deprecated(message, stacklevel=2):
48 def decorator(f):
49 @functools.wraps(f)
50 def wrapper(*args, **kwargs):
51 warnings.warn(message, DeprecationWarning, stacklevel=stacklevel)
52 return f(*args, **kwargs)
53 return wrapper
54 return decorator
55
56
57 def extend(cls):
58 def decorator(f):
59 if isinstance(f, property):
60 name = f.fget.__name__
61 else:
62 name = f.__name__
63 setattr(cls, name, f)
64 return decorator