c9e95cc6e585bda3610f6ab24612f0b8a41201a3
[nmutil.git] / src / nmutil / util.py
1 from collections.abc import Iterable
2 from nmigen import Mux, Signal
3
4 # XXX this already exists in nmigen._utils
5 # see https://bugs.libre-soc.org/show_bug.cgi?id=297
6 def flatten(v):
7 if isinstance(v, Iterable):
8 for i in v:
9 yield from flatten(i)
10 else:
11 yield v
12
13 # tree reduction function. operates recursively.
14 def treereduce(tree, op, fn):
15 """treereduce: apply a map-reduce to a list.
16 examples: OR-reduction of one member of a list of Records down to a
17 single data point:
18 treereduce(tree, operator.or_, lambda x: getattr(x, "data_o"))
19 """
20 #print ("treereduce", tree)
21 if not isinstance(tree, list):
22 return tree
23 if len(tree) == 1:
24 return fn(tree[0])
25 if len(tree) == 2:
26 return op(fn(tree[0]), fn(tree[1]))
27 s = len(tree) // 2 # splitpoint
28 return op(treereduce(tree[:s], op, fn),
29 treereduce(tree[s:], op, fn))
30
31 # chooses assignment of 32 bit or full 64 bit depending on is_32bit
32 def eq32(is_32bit, dest, src):
33 return [dest[0:32].eq(src[0:32]),
34 dest[32:64].eq(Mux(is_32bit, 0, src[32:64]))]
35
36
37 # a wrapper function formerly in run_simulation that is still useful.
38 # Simulation.add_sync_process now only takes functions, it does not
39 # take generators. so passing in arguments is no longer possible.
40 # with this wrapper, the following is possible:
41 # sim.add_sync_process(wrap.dut(parallel_sender_number=0))
42 # sim.add_sync_process(wrap.dut(parallel_sender_number=1))
43
44 def wrap(process):
45 def wrapper():
46 yield from process
47 return wrapper
48
49
50 # a "rising edge" generator. can take signals of greater than width 1
51
52 def rising_edge(m, sig):
53 delay = Signal.like(sig)
54 rising = Signal.like(sig)
55 delay.name = "%s_dly" % sig.name
56 rising.name = "%s_rise" % sig.name
57 m.d.sync += delay.eq(sig) # 1 clock delay
58 m.d.comb += rising.eq(sig & ~delay) # sig is hi but delay-sig is lo
59 return rising
60
61
62 # Display function (dummy if non-existent)
63 # added as a patch from jeanthom
64 # https://gist.githubusercontent.com/jeanthom/
65 # f97f5b928720d4adda9d295e8a5bc078/
66 # raw/694274e0aceec993c0fc127e296b1a85b93c1b89/nmigen-display.diff
67 try:
68 from nmigen.hdl.ast import Display
69 except ImportError:
70 def Display(*args):
71 return []
72