big convert g/s/r mid --> muxid
[ieee754fpu.git] / src / ieee754 / add / inputgroup.py
1 from nmigen import Module, Signal, Cat, Array, Const
2 from nmigen.lib.coding import PriorityEncoder
3 from math import log
4
5 from ieee754.fpcommon.fpbase import Trigger
6
7
8 class FPGetSyncOpsMod:
9 def __init__(self, width, num_ops=2):
10 self.width = width
11 self.num_ops = num_ops
12 inops = []
13 outops = []
14 for i in range(num_ops):
15 inops.append(Signal(width, reset_less=True))
16 outops.append(Signal(width, reset_less=True))
17 self.in_op = inops
18 self.out_op = outops
19 self.stb = Signal(num_ops)
20 self.ack = Signal()
21 self.ready = Signal(reset_less=True)
22 self.out_decode = Signal(reset_less=True)
23
24 def elaborate(self, platform):
25 m = Module()
26 m.d.comb += self.ready.eq(self.stb == Const(-1, (self.num_ops, False)))
27 m.d.comb += self.out_decode.eq(self.ack & self.ready)
28 with m.If(self.out_decode):
29 for i in range(self.num_ops):
30 m.d.comb += [
31 self.out_op[i].eq(self.in_op[i]),
32 ]
33 return m
34
35 def ports(self):
36 return self.in_op + self.out_op + [self.stb, self.ack]
37
38
39 class FPOps(Trigger):
40 def __init__(self, width, num_ops):
41 Trigger.__init__(self)
42 self.width = width
43 self.num_ops = num_ops
44
45 res = []
46 for i in range(num_ops):
47 res.append(Signal(width))
48 self.v = Array(res)
49
50 def ports(self):
51 res = []
52 for i in range(self.num_ops):
53 res.append(self.v[i])
54 res.append(self.ack)
55 res.append(self.stb)
56 return res
57
58
59 class InputGroup:
60 def __init__(self, width, num_ops=2, num_rows=4):
61 self.width = width
62 self.num_ops = num_ops
63 self.num_rows = num_rows
64 self.mmax = int(log(self.num_rows) / log(2))
65 self.rs = []
66 self.muxid = Signal(self.mmax, reset_less=True) # multiplex id
67 for i in range(num_rows):
68 self.rs.append(FPGetSyncOpsMod(width, num_ops))
69 self.rs = Array(self.rs)
70
71 self.out_op = FPOps(width, num_ops)
72
73 def elaborate(self, platform):
74 m = Module()
75
76 pe = PriorityEncoder(self.num_rows)
77 m.submodules.selector = pe
78 m.submodules.out_op = self.out_op
79 m.submodules += self.rs
80
81 # connect priority encoder
82 in_ready = []
83 for i in range(self.num_rows):
84 in_ready.append(self.rs[i].ready)
85 m.d.comb += pe.i.eq(Cat(*in_ready))
86
87 active = Signal(reset_less=True)
88 out_en = Signal(reset_less=True)
89 m.d.comb += active.eq(~pe.n) # encoder active
90 m.d.comb += out_en.eq(active & self.out_op.trigger)
91
92 # encoder active: ack relevant input, record MID, pass output
93 with m.If(out_en):
94 rs = self.rs[pe.o]
95 m.d.sync += self.muxid.eq(pe.o)
96 m.d.sync += rs.ack.eq(0)
97 m.d.sync += self.out_op.stb.eq(0)
98 for j in range(self.num_ops):
99 m.d.sync += self.out_op.v[j].eq(rs.out_op[j])
100 with m.Else():
101 m.d.sync += self.out_op.stb.eq(1)
102 # acks all default to zero
103 for i in range(self.num_rows):
104 m.d.sync += self.rs[i].ack.eq(1)
105
106 return m
107
108 def ports(self):
109 res = []
110 for i in range(self.num_rows):
111 inop = self.rs[i]
112 res += inop.in_op + [inop.stb]
113 return self.out_op.ports() + res + [self.muxid]
114
115