use get_op functions, easier to do
[ieee754fpu.git] / src / add / fmul.py
1 from nmigen import Module, Signal
2 from nmigen.cli import main, verilog
3
4 from fpbase import FPNum, FPOp, Overflow, FPBase
5
6
7 class FPMUL(FPBase):
8
9 def __init__(self, width):
10 FPBase.__init__(self)
11 self.width = width
12
13 self.in_a = FPOp(width)
14 self.in_b = FPOp(width)
15 self.out_z = FPOp(width)
16
17 def get_fragment(self, platform=None):
18 """ creates the HDL code-fragment for FPMUL
19 """
20 m = Module()
21
22 # Latches
23 a = FPNum(self.width, False)
24 b = FPNum(self.width, False)
25 z = FPNum(self.width, False)
26
27 mw = (self.m_width)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
28 product = Signal(mw)
29
30 of = Overflow()
31
32 with m.FSM() as fsm:
33
34 # ******
35 # gets operand a
36
37 with m.State("get_a"):
38 self.get_op(m, self.in_a, a, "get_b")
39
40 # ******
41 # gets operand b
42
43 with m.State("get_b"):
44 self.get_op(m, self.in_b, b, "special_cases")
45
46 # ******
47 # special cases
48
49 with m.State("special_cases"):
50 m.next = "normalise_a"
51 #if a or b is NaN return NaN
52 with m.If(a.is_nan() | b.is_nan()):
53 m.next += "put_z"
54 m.d.sync += z.nan(1)
55 #if a is inf return inf
56 with m.Elif(a.is_inf()):
57 m.next += "put_z"
58 m.d.sync += z.inf(0)
59 #if b is zero return NaN
60 with m.If(b.is_zero()):
61 m.d.sync += z.nan(1)
62 #if b is inf return inf
63 with m.Elif(b.is_inf()):
64 m.next += "put_z"
65 m.d.sync += z.inf(0)
66 #if a is zero return NaN
67 with m.If(a.is_zero()):
68 m.next += "put_z"
69 m.d.sync += z.nan(1)
70 #if a is zero return zero
71 with m.Elif(a.is_zero()):
72 m.next += "put_z"
73 m.d.sync += z.zero(0)
74 #if b is zero return zero
75 with m.Elif(b.is_zero()):
76 m.next += "put_z"
77 m.d.sync += z.zero(0)
78 # Denormalised Number checks
79 with m.Else():
80 m.next += "normalise_a"
81 self.denormalise(m, a)
82 self.denormalise(m, b)
83
84 # ******
85 # normalise_a
86
87 with m.State("normalise_a"):
88 self.op_normalise(m, a, "normalise_b")
89
90 # ******
91 # normalise_b
92
93 with m.State("normalise_b"):
94 self.op_normalise(m, b, "multiply_0")
95
96 #multiply_0
97 with m.State("multiply_0"):
98 m.next += "multiply_1"
99 m.d.sync += [
100 z.s.eq(a.s ^ b.s),
101 z.e.eq(a.e + b.e + 1),
102 product.eq(a.m * b.m * 4)
103 ]
104
105 #multiply_1
106 with m.State("multiply_1"):
107 m.next += "normalise_1"
108 m.d.sync += [
109 z.m.eq(product[26:50]),
110 guard.eq(product[25]),
111 round_bit.eq(product[24]),
112 sticky.eq(product[0:23] != 0)
113 ]
114
115 # ******
116 # First stage of normalisation.
117 with m.State("normalise_1"):
118 self.normalise_1(m, z, of, "normalise_2")
119
120 # ******
121 # Second stage of normalisation.
122
123 with m.State("normalise_2"):
124 self.normalise_2(m, z, of, "round")
125
126 # ******
127 # rounding stage
128
129 with m.State("round"):
130 self.roundz(m, z, of, "corrections")
131
132 # ******
133 # pack stage
134 with m.State("pack"):
135 self.pack(m, z, "put_z")
136
137 # ******
138 # put_z stage
139
140 with m.State("put_z"):
141 self.put_z(m, z, self.out_z, "get_a")
142
143 return m
144
145 """
146 special_cases:
147 begin
148 //if a is NaN or b is NaN return NaN
149 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
150 z[31] <= 1;
151 z[30:23] <= 255;
152 z[22] <= 1;
153 z[21:0] <= 0;
154 state <= put_z;
155 //if a is inf return inf
156 end else if (a_e == 128) begin
157 z[31] <= a_s ^ b_s;
158 z[30:23] <= 255;
159 z[22:0] <= 0;
160 //if b is zero return NaN
161 if (($signed(b_e) == -127) && (b_m == 0)) begin
162 z[31] <= 1;
163 z[30:23] <= 255;
164 z[22] <= 1;
165 z[21:0] <= 0;
166 end
167 state <= put_z;
168 //if b is inf return inf
169 end else if (b_e == 128) begin
170 z[31] <= a_s ^ b_s;
171 z[30:23] <= 255;
172 z[22:0] <= 0;
173 //if a is zero return NaN
174 if (($signed(a_e) == -127) && (a_m == 0)) begin
175 z[31] <= 1;
176 z[30:23] <= 255;
177 z[22] <= 1;
178 z[21:0] <= 0;
179 end
180 state <= put_z;
181 //if a is zero return zero
182 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
183 z[31] <= a_s ^ b_s;
184 z[30:23] <= 0;
185 z[22:0] <= 0;
186 state <= put_z;
187 //if b is zero return zero
188 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
189 z[31] <= a_s ^ b_s;
190 z[30:23] <= 0;
191 z[22:0] <= 0;
192 state <= put_z;
193 //^ done up to here
194 end else begin
195 //Denormalised Number
196 if ($signed(a_e) == -127) begin
197 a_e <= -126;
198 end else begin
199 a_m[23] <= 1;
200 end
201 //Denormalised Number
202 if ($signed(b_e) == -127) begin
203 b_e <= -126;
204 end else begin
205 b_m[23] <= 1;
206 end
207 state <= normalise_a;
208 end
209 end
210
211 normalise_a:
212 begin
213 if (a_m[23]) begin
214 state <= normalise_b;
215 end else begin
216 a_m <= a_m << 1;
217 a_e <= a_e - 1;
218 end
219 end
220
221 normalise_b:
222 begin
223 if (b_m[23]) begin
224 state <= multiply_0;
225 end else begin
226 b_m <= b_m << 1;
227 b_e <= b_e - 1;
228 end
229 end
230
231 multiply_0:
232 begin
233 z_s <= a_s ^ b_s;
234 z_e <= a_e + b_e + 1;
235 product <= a_m * b_m * 4;
236 state <= multiply_1;
237 end
238
239 multiply_1:
240 begin
241 z_m <= product[49:26];
242 guard <= product[25];
243 round_bit <= product[24];
244 sticky <= (product[23:0] != 0);
245 state <= normalise_1;
246 end
247
248 normalise_1:
249 begin
250 if (z_m[23] == 0) begin
251 z_e <= z_e - 1;
252 z_m <= z_m << 1;
253 z_m[0] <= guard;
254 guard <= round_bit;
255 round_bit <= 0;
256 end else begin
257 state <= normalise_2;
258 end
259 end
260
261 normalise_2:
262 begin
263 if ($signed(z_e) < -126) begin
264 z_e <= z_e + 1;
265 z_m <= z_m >> 1;
266 guard <= z_m[0];
267 round_bit <= guard;
268 sticky <= sticky | round_bit;
269 end else begin
270 state <= round;
271 end
272 end
273
274 round:
275 begin
276 if (guard && (round_bit | sticky | z_m[0])) begin
277 z_m <= z_m + 1;
278 if (z_m == 24'hffffff) begin
279 z_e <=z_e + 1;
280 end
281 end
282 state <= pack;
283 end
284
285 pack:
286 begin
287 z[22 : 0] <= z_m[22:0];
288 z[30 : 23] <= z_e[7:0] + 127;
289 z[31] <= z_s;
290 if ($signed(z_e) == -126 && z_m[23] == 0) begin
291 z[30 : 23] <= 0;
292 end
293 //if overflow occur
294 s, return inf
295 if ($signed(z_e) > 127) begin
296 z[22 : 0] <= 0;
297 z[30 : 23] <= 255;
298 z[31] <= z_s;
299 end
300 state <= put_z;
301 end
302
303 put_z:
304 begin
305 s_output_z_stb <= 1;
306 s_output_z <= z;
307 if (s_output_z_stb && output_z_ack) begin
308 s_output_z_stb <= 0;
309 state <= get_a;
310 end
311 end
312
313 """
314
315 if __name__ == "__main__":
316 alu = FPMUL(width=32)
317 main(alu, ports=alu.in_a.ports() + alu.in_b.ports() + alu.out_z.ports())