add operand down pipeline chain
[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.mid = 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.mid.eq(i.mid)]
80
81 def ports(self):
82 return [self.a, self.b, self.mid]
83
84
85 class FPBaseData:
86
87 def __init__(self, n_ops, width, id_wid, op_wid):
88 self.width = width
89 self.id_wid = id_wid
90 self.op_wid = op_wid
91 ops = []
92 for i in range(n_ops):
93 name = chr(ord("a")+i)
94 operand = Signal(width, name=name)
95 setattr(self, name, operand)
96 ops.append(operand)
97 self.ops = ops
98 self.mid = Signal(id_wid, reset_less=True) # RS multiplex ID
99 self.op = Signal(op_wid, reset_less=True)
100
101 def eq(self, i):
102 ret = []
103 for op1, op2 in zip(self.ops, i.ops):
104 ret.append(op1.eq(op2))
105 ret.append(self.mid.eq(i.mid))
106 if self.op_wid:
107 ret.append(self.op.eq(i.op))
108 return ret
109
110 def __iter__(self):
111 if self.ops:
112 yield from self.ops
113 yield self.mid
114 if self.id_wid:
115 yield self.op
116
117 def ports(self):
118 return list(self)
119
120 class FPADDBaseData(FPBaseData):
121
122 def __init__(self, width, id_wid, op_wid):
123 FPBaseData.__init__(self, 2, width, id_wid, op_wid)
124
125
126 class FPGet2OpMod(PrevControl):
127 def __init__(self, width, id_wid, op_wid=None):
128 PrevControl.__init__(self)
129 self.width = width
130 self.id_wid = id_wid
131 self.data_i = self.ispec()
132 self.i = self.data_i
133 self.o = self.ospec()
134
135 def ispec(self):
136 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
137
138 def ospec(self):
139 return FPADDBaseData(self.width, self.id_wid, self.op_wid)
140
141 def process(self, i):
142 return self.o
143
144 def elaborate(self, platform):
145 m = PrevControl.elaborate(self, platform)
146 with m.If(self.trigger):
147 m.d.comb += [
148 self.o.eq(self.data_i),
149 ]
150 return m
151
152
153 class FPGet2Op(FPState):
154 """ gets operands
155 """
156
157 def __init__(self, in_state, out_state, width, id_wid, op_wid=None):
158 FPState.__init__(self, in_state)
159 self.out_state = out_state
160 self.mod = FPGet2OpMod(width, id_wid, op_wid)
161 self.o = self.ospec()
162 self.in_stb = Signal(reset_less=True)
163 self.out_ack = Signal(reset_less=True)
164 self.out_decode = Signal(reset_less=True)
165
166 def ispec(self):
167 return self.mod.ispec()
168
169 def ospec(self):
170 return self.mod.ospec()
171
172 def trigger_setup(self, m, in_stb, in_ack):
173 """ links stb/ack
174 """
175 m.d.comb += self.mod.valid_i.eq(in_stb)
176 m.d.comb += in_ack.eq(self.mod.ready_o)
177
178 def setup(self, m, i):
179 """ links module to inputs and outputs
180 """
181 m.submodules.get_ops = self.mod
182 m.d.comb += self.mod.i.eq(i)
183 m.d.comb += self.out_ack.eq(self.mod.ready_o)
184 m.d.comb += self.out_decode.eq(self.mod.trigger)
185
186 def process(self, i):
187 return self.o
188
189 def action(self, m):
190 with m.If(self.out_decode):
191 m.next = self.out_state
192 m.d.sync += [
193 self.mod.ready_o.eq(0),
194 self.o.eq(self.mod.o),
195 ]
196 with m.Else():
197 m.d.sync += self.mod.ready_o.eq(1)
198
199