big convert g/s/r mid --> muxid
[ieee754fpu.git] / src / ieee754 / fpcommon / getop.py
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
3 # 2013-12-12
4
5 from nmigen import Module, Signal, Cat, Mux, Array, Const, Elaboratable
6 from nmigen.lib.coding import PriorityEncoder
7 from nmigen.cli import main, verilog
8 from math import log
9
10 from ieee754.fpcommon.fpbase import FPNumIn, FPNumOut, FPOpIn, Overflow, FPBase, FPNumBase
11 from ieee754.fpcommon.fpbase import MultiShiftRMerge, Trigger
12 from nmutil.singlepipe import (ControlBase, StageChain, SimpleHandshake,
13 PassThroughStage, PrevControl)
14 from nmutil.multipipe import CombMuxOutPipe
15 from nmutil.multipipe import PriorityCombMuxInPipe
16
17 from ieee754.fpcommon.fpbase import FPState
18 from nmutil import nmoperator
19
20
21 class FPGetOpMod(Elaboratable):
22 def __init__(self, width):
23 self.in_op = FPOpIn(width)
24 self.in_op.data_i = Signal(width)
25 self.out_op = Signal(width)
26 self.out_decode = Signal(reset_less=True)
27
28 def elaborate(self, platform):
29 m = Module()
30 m.d.comb += self.out_decode.eq((self.in_op.ready_o) & \
31 (self.in_op.valid_i_test))
32 m.submodules.get_op_in = self.in_op
33 #m.submodules.get_op_out = self.out_op
34 with m.If(self.out_decode):
35 m.d.comb += [
36 self.out_op.eq(self.in_op.v),
37 ]
38 return m
39
40
41 class FPGetOp(FPState):
42 """ gets operand
43 """
44
45 def __init__(self, in_state, out_state, in_op, width):
46 FPState.__init__(self, in_state)
47 self.out_state = out_state
48 self.mod = FPGetOpMod(width)
49 self.in_op = in_op
50 self.out_op = Signal(width)
51 self.out_decode = Signal(reset_less=True)
52
53 def setup(self, m, in_op):
54 """ links module to inputs and outputs
55 """
56 setattr(m.submodules, self.state_from, self.mod)
57 m.d.comb += nmoperator.eq(self.mod.in_op, in_op)
58 m.d.comb += self.out_decode.eq(self.mod.out_decode)
59
60 def action(self, m):
61 with m.If(self.out_decode):
62 m.next = self.out_state
63 m.d.sync += [
64 self.in_op.ready_o.eq(0),
65 self.out_op.eq(self.mod.out_op)
66 ]
67 with m.Else():
68 m.d.sync += self.in_op.ready_o.eq(1)
69
70
71 class FPNumBase2Ops:
72
73 def __init__(self, width, id_wid, m_extra=True):
74 self.a = FPNumBase(width, m_extra)
75 self.b = FPNumBase(width, m_extra)
76 self.muxid = Signal(id_wid, reset_less=True)
77
78 def eq(self, i):
79 return [self.a.eq(i.a), self.b.eq(i.b), self.muxid.eq(i.muxid)]
80
81 def ports(self):
82 return [self.a, self.b, self.muxid]
83
84
85 class FPBaseData:
86
87 def __init__(self, width, pspec):
88 self.width = width
89 print (pspec)
90 self.id_wid = pspec['id_wid']
91 self.op_wid = pspec.get('op_wid', 0)
92 self.muxid = Signal(self.id_wid, reset_less=True) # RS multiplex ID
93 self.op = Signal(self.op_wid, reset_less=True)
94
95 def eq(self, i):
96 ret = [self.muxid.eq(i.muxid)]
97 if self.op_wid:
98 ret.append(self.op.eq(i.op))
99 return ret
100
101 def __iter__(self):
102 yield self.muxid
103 if self.op_wid:
104 yield self.op
105
106 def ports(self):
107 return list(self)
108
109
110 class FPADDBaseData:
111
112 def __init__(self, width, pspec, n_ops=2):
113 self.width = width
114 self.ctx = FPBaseData(width, pspec)
115 ops = []
116 for i in range(n_ops):
117 name = chr(ord("a")+i)
118 operand = Signal(width, name=name)
119 setattr(self, name, operand)
120 ops.append(operand)
121 self.muxid = self.ctx.muxid # make muxid available here: complicated
122 self.ops = ops
123
124 def eq(self, i):
125 ret = []
126 for op1, op2 in zip(self.ops, i.ops):
127 ret.append(op1.eq(op2))
128 ret.append(self.ctx.eq(i.ctx))
129 return ret
130
131 def __iter__(self):
132 if self.ops:
133 yield from self.ops
134 yield from self.ctx
135
136 def ports(self):
137 return list(self)
138
139
140 class FPGet2OpMod(PrevControl):
141 def __init__(self, width, id_wid, op_wid=None):
142 PrevControl.__init__(self)
143 self.width = width
144 self.id_wid = id_wid
145 self.data_i = self.ispec()
146 self.i = self.data_i
147 self.o = self.ospec()
148
149 def ispec(self):
150 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
151
152 def ospec(self):
153 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
154
155 def process(self, i):
156 return self.o
157
158 def elaborate(self, platform):
159 m = PrevControl.elaborate(self, platform)
160 with m.If(self.trigger):
161 m.d.comb += [
162 self.o.eq(self.data_i),
163 ]
164 return m
165
166
167 class FPGet2Op(FPState):
168 """ gets operands
169 """
170
171 def __init__(self, in_state, out_state, width, id_wid, op_wid=None):
172 FPState.__init__(self, in_state)
173 self.out_state = out_state
174 self.mod = FPGet2OpMod(width, id_wid, op_wid)
175 self.o = self.ospec()
176 self.in_stb = Signal(reset_less=True)
177 self.out_ack = Signal(reset_less=True)
178 self.out_decode = Signal(reset_less=True)
179
180 def ispec(self):
181 return self.mod.ispec()
182
183 def ospec(self):
184 return self.mod.ospec()
185
186 def trigger_setup(self, m, in_stb, in_ack):
187 """ links stb/ack
188 """
189 m.d.comb += self.mod.valid_i.eq(in_stb)
190 m.d.comb += in_ack.eq(self.mod.ready_o)
191
192 def setup(self, m, i):
193 """ links module to inputs and outputs
194 """
195 m.submodules.get_ops = self.mod
196 m.d.comb += self.mod.i.eq(i)
197 m.d.comb += self.out_ack.eq(self.mod.ready_o)
198 m.d.comb += self.out_decode.eq(self.mod.trigger)
199
200 def process(self, i):
201 return self.o
202
203 def action(self, m):
204 with m.If(self.out_decode):
205 m.next = self.out_state
206 m.d.sync += [
207 self.mod.ready_o.eq(0),
208 self.o.eq(self.mod.o),
209 ]
210 with m.Else():
211 m.d.sync += self.mod.ready_o.eq(1)
212
213