try some more chaining of inputs to outputs
[ieee754fpu.git] / src / add / nmigen_add_experiment.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
6 from nmigen.cli import main, verilog
7
8 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase
9
10
11 class FPState(FPBase):
12 def __init__(self, state_from):
13 self.state_from = state_from
14
15 def set_inputs(self, inputs):
16 self.inputs = inputs
17 for k,v in inputs.items():
18 setattr(self, k, v)
19
20 def set_outputs(self, outputs):
21 self.outputs = outputs
22 for k,v in outputs.items():
23 setattr(self, k, v)
24
25
26 class FPGetOpA(FPState):
27 """ gets operand a
28 """
29
30 def __init__(self, in_a, width):
31 FPState.__init__(self, "get_a")
32 self.in_a = in_a
33 self.a = FPNumIn(in_a, width)
34
35 def action(self, m):
36 self.get_op(m, self.in_a, self.a, "get_b")
37
38
39 class FPGetOpB(FPState):
40 """ gets operand b
41 """
42
43 def action(self, m):
44 self.get_op(m, self.in_b, self.b, "special_cases")
45
46
47 class FPAddSpecialCasesMod:
48 """ special cases: NaNs, infs, zeros, denormalised
49 NOTE: some of these are unique to add. see "Special Operations"
50 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
51 """
52
53 def __init__(self, width):
54 self.in_a = FPNumBase(width)
55 self.in_b = FPNumBase(width)
56 self.out_z = FPNumOut(width, False)
57 self.out_do_z = Signal(reset_less=True)
58
59 def setup(self, m, in_a, in_b, out_z, out_do_z):
60 """ links module to inputs and outputs
61 """
62 m.d.comb += self.in_a.copy(in_a)
63 m.d.comb += self.in_b.copy(in_b)
64 m.d.comb += out_z.v.eq(self.out_z.v)
65 m.d.comb += out_do_z.eq(self.out_do_z)
66
67 def elaborate(self, platform):
68 m = Module()
69
70 m.submodules.sc_in_a = self.in_a
71 m.submodules.sc_in_b = self.in_b
72 m.submodules.sc_out_z = self.out_z
73
74 s_nomatch = Signal()
75 m.d.comb += s_nomatch.eq(self.in_a.s != self.in_b.s)
76
77 m_match = Signal()
78 m.d.comb += m_match.eq(self.in_a.m == self.in_b.m)
79
80 # if a is NaN or b is NaN return NaN
81 with m.If(self.in_a.is_nan | self.in_b.is_nan):
82 m.d.comb += self.out_do_z.eq(1)
83 m.d.comb += self.out_z.nan(1)
84
85 # XXX WEIRDNESS for FP16 non-canonical NaN handling
86 # under review
87
88 ## if a is zero and b is NaN return -b
89 #with m.If(a.is_zero & (a.s==0) & b.is_nan):
90 # m.d.comb += self.out_do_z.eq(1)
91 # m.d.comb += z.create(b.s, b.e, Cat(b.m[3:-2], ~b.m[0]))
92
93 ## if b is zero and a is NaN return -a
94 #with m.Elif(b.is_zero & (b.s==0) & a.is_nan):
95 # m.d.comb += self.out_do_z.eq(1)
96 # m.d.comb += z.create(a.s, a.e, Cat(a.m[3:-2], ~a.m[0]))
97
98 ## if a is -zero and b is NaN return -b
99 #with m.Elif(a.is_zero & (a.s==1) & b.is_nan):
100 # m.d.comb += self.out_do_z.eq(1)
101 # m.d.comb += z.create(a.s & b.s, b.e, Cat(b.m[3:-2], 1))
102
103 ## if b is -zero and a is NaN return -a
104 #with m.Elif(b.is_zero & (b.s==1) & a.is_nan):
105 # m.d.comb += self.out_do_z.eq(1)
106 # m.d.comb += z.create(a.s & b.s, a.e, Cat(a.m[3:-2], 1))
107
108 # if a is inf return inf (or NaN)
109 with m.Elif(self.in_a.is_inf):
110 m.d.comb += self.out_do_z.eq(1)
111 m.d.comb += self.out_z.inf(self.in_a.s)
112 # if a is inf and signs don't match return NaN
113 with m.If(self.in_b.exp_128 & s_nomatch):
114 m.d.comb += self.out_z.nan(1)
115
116 # if b is inf return inf
117 with m.Elif(self.in_b.is_inf):
118 m.d.comb += self.out_do_z.eq(1)
119 m.d.comb += self.out_z.inf(self.in_b.s)
120
121 # if a is zero and b zero return signed-a/b
122 with m.Elif(self.in_a.is_zero & self.in_b.is_zero):
123 m.d.comb += self.out_do_z.eq(1)
124 m.d.comb += self.out_z.create(self.in_a.s & self.in_b.s,
125 self.in_b.e,
126 self.in_b.m[3:-1])
127
128 # if a is zero return b
129 with m.Elif(self.in_a.is_zero):
130 m.d.comb += self.out_do_z.eq(1)
131 m.d.comb += self.out_z.create(self.in_b.s, self.in_b.e,
132 self.in_b.m[3:-1])
133
134 # if b is zero return a
135 with m.Elif(self.in_b.is_zero):
136 m.d.comb += self.out_do_z.eq(1)
137 m.d.comb += self.out_z.create(self.in_a.s, self.in_a.e,
138 self.in_a.m[3:-1])
139
140 # if a equal to -b return zero (+ve zero)
141 with m.Elif(s_nomatch & m_match & (self.in_a.e == self.in_b.e)):
142 m.d.comb += self.out_do_z.eq(1)
143 m.d.comb += self.out_z.zero(0)
144
145 # Denormalised Number checks
146 with m.Else():
147 m.d.comb += self.out_do_z.eq(0)
148
149 return m
150
151
152 class FPAddSpecialCases(FPState):
153 """ special cases: NaNs, infs, zeros, denormalised
154 NOTE: some of these are unique to add. see "Special Operations"
155 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
156 """
157
158 def __init__(self, width):
159 FPState.__init__(self, "special_cases")
160 self.mod = FPAddSpecialCasesMod(width)
161 self.out_z = FPNumOut(width, False)
162 self.out_do_z = Signal(reset_less=True)
163
164 def action(self, m):
165 with m.If(self.out_do_z):
166 m.d.sync += self.z.v.eq(self.out_z.v) # only take the output
167 m.next = "put_z"
168 with m.Else():
169 m.next = "denormalise"
170
171
172 class FPAddDeNorm(FPState):
173
174 def action(self, m):
175 # Denormalised Number checks
176 m.next = "align"
177 self.denormalise(m, self.a)
178 self.denormalise(m, self.b)
179
180
181 class FPAddAlignMulti(FPState):
182
183 def action(self, m):
184 # NOTE: this does *not* do single-cycle multi-shifting,
185 # it *STAYS* in the align state until exponents match
186
187 # exponent of a greater than b: shift b down
188 with m.If(self.a.e > self.b.e):
189 m.d.sync += self.b.shift_down()
190 # exponent of b greater than a: shift a down
191 with m.Elif(self.a.e < self.b.e):
192 m.d.sync += self.a.shift_down()
193 # exponents equal: move to next stage.
194 with m.Else():
195 m.next = "add_0"
196
197
198 class FPAddAlignSingle(FPState):
199
200 def action(self, m):
201 # This one however (single-cycle) will do the shift
202 # in one go.
203
204 # XXX TODO: the shifter used here is quite expensive
205 # having only one would be better
206
207 ediff = Signal((len(self.a.e), True), reset_less=True)
208 ediffr = Signal((len(self.a.e), True), reset_less=True)
209 m.d.comb += ediff.eq(self.a.e - self.b.e)
210 m.d.comb += ediffr.eq(self.b.e - self.a.e)
211 with m.If(ediff > 0):
212 m.d.sync += self.b.shift_down_multi(ediff)
213 # exponent of b greater than a: shift a down
214 with m.Elif(ediff < 0):
215 m.d.sync += self.a.shift_down_multi(ediffr)
216
217 m.next = "add_0"
218
219
220 class FPAddStage0Mod:
221
222 def __init__(self, width):
223 self.in_a = FPNumBase(width)
224 self.in_b = FPNumBase(width)
225 self.in_z = FPNumBase(width, False)
226 self.out_z = FPNumBase(width, False)
227 self.out_tot = Signal(self.out_z.m_width + 4, reset_less=True)
228
229 def setup(self, m, in_a, in_b, in_z, out_z, out_tot):
230 """ links module to inputs and outputs
231 """
232 m.d.comb += self.in_a.copy(in_a)
233 m.d.comb += self.in_b.copy(in_b)
234 m.d.comb += self.in_z.copy(in_z)
235 m.d.comb += out_z.copy(self.out_z)
236 m.d.comb += out_tot.eq(self.out_tot)
237
238 def elaborate(self, platform):
239 m = Module()
240 #m.submodules.add0_in_a = self.in_a
241 #m.submodules.add0_in_b = self.in_b
242 #m.submodules.add0_in_z = self.in_z
243 #m.submodules.add0_out_z = self.out_z
244
245 m.d.comb += self.out_z.e.eq(self.in_a.e)
246 # same-sign (both negative or both positive) add mantissas
247 with m.If(self.in_a.s == self.in_b.s):
248 m.d.comb += [
249 self.out_tot.eq(Cat(self.in_a.m, 0) + Cat(self.in_b.m, 0)),
250 self.out_z.s.eq(self.in_a.s)
251 ]
252 # a mantissa greater than b, use a
253 with m.Elif(self.in_a.m >= self.in_b.m):
254 m.d.comb += [
255 self.out_tot.eq(Cat(self.in_a.m, 0) - Cat(self.in_b.m, 0)),
256 self.out_z.s.eq(self.in_a.s)
257 ]
258 # b mantissa greater than a, use b
259 with m.Else():
260 m.d.comb += [
261 self.out_tot.eq(Cat(self.in_b.m, 0) - Cat(self.in_a.m, 0)),
262 self.out_z.s.eq(self.in_b.s)
263 ]
264 return m
265
266
267 class FPAddStage0(FPState):
268 """ First stage of add. covers same-sign (add) and subtract
269 special-casing when mantissas are greater or equal, to
270 give greatest accuracy.
271 """
272
273 def __init__(self, width):
274 FPState.__init__(self, "add_0")
275 self.mod = FPAddStage0Mod(width)
276 self.out_z = FPNumBase(width, False)
277 self.out_tot = Signal(self.out_z.m_width + 4, reset_less=True)
278
279 def action(self, m):
280 m.next = "add_1"
281 m.d.sync += self.tot.eq(self.out_tot)
282 m.d.sync += self.z.copy(self.out_z)
283
284
285 class FPAddStage1(FPState):
286 """ Second stage of add: preparation for normalisation.
287 detects when tot sum is too big (tot[27] is kinda a carry bit)
288 """
289
290 def action(self, m):
291 m.next = "normalise_1"
292 # tot[27] gets set when the sum overflows. shift result down
293 with m.If(self.tot[-1]):
294 m.d.sync += [
295 self.z.m.eq(self.tot[4:]),
296 self.of.m0.eq(self.tot[4]),
297 self.of.guard.eq(self.tot[3]),
298 self.of.round_bit.eq(self.tot[2]),
299 self.of.sticky.eq(self.tot[1] | self.tot[0]),
300 self.z.e.eq(self.z.e + 1)
301 ]
302 # tot[27] zero case
303 with m.Else():
304 m.d.sync += [
305 self.z.m.eq(self.tot[3:]),
306 self.of.m0.eq(self.tot[3]),
307 self.of.guard.eq(self.tot[2]),
308 self.of.round_bit.eq(self.tot[1]),
309 self.of.sticky.eq(self.tot[0])
310 ]
311
312
313 class FPNorm1Mod:
314
315 def __init__(self, width):
316 self.out_norm = Signal(reset_less=True)
317 self.in_z = FPNumBase(width, False)
318 self.out_z = FPNumBase(width, False)
319 self.in_of = Overflow()
320 self.out_of = Overflow()
321
322 def setup(self, m, in_z, out_z, in_of, out_of, out_norm):
323 """ links module to inputs and outputs
324 """
325 m.d.comb += self.in_z.copy(in_z)
326 m.d.comb += out_z.copy(self.out_z)
327 m.d.comb += self.in_of.copy(in_of)
328 m.d.comb += out_of.copy(self.out_of)
329 m.d.comb += out_norm.eq(self.out_norm)
330
331 def elaborate(self, platform):
332 m = Module()
333 m.submodules.norm1_in_overflow = self.in_of
334 m.submodules.norm1_out_overflow = self.out_of
335 m.submodules.norm1_in_z = self.in_z
336 m.submodules.norm1_out_z = self.out_z
337 m.d.comb += self.out_z.copy(self.in_z)
338 m.d.comb += self.out_of.copy(self.in_of)
339 m.d.comb += self.out_norm.eq((self.in_z.m_msbzero) & \
340 (self.in_z.exp_gt_n126))
341 with m.If(self.out_norm):
342 m.d.comb += [
343 self.out_z.e.eq(self.in_z.e - 1), # DECREASE exponent
344 self.out_z.m.eq(self.in_z.m << 1), # shift mantissa UP
345 self.out_z.m[0].eq(self.in_of.guard), # steal guard (was tot[2])
346 self.out_of.guard.eq(self.in_of.round_bit), # round (was tot[1])
347 self.out_of.round_bit.eq(0), # reset round bit
348 self.out_of.m0.eq(self.in_of.guard),
349 ]
350
351 return m
352
353
354 class FPNorm1(FPState):
355
356 def __init__(self, width):
357 FPState.__init__(self, "normalise_1")
358 self.mod = FPNorm1Mod(width)
359 self.out_norm = Signal(reset_less=True)
360 self.out_z = FPNumBase(width)
361 self.out_of = Overflow()
362
363 def action(self, m):
364 m.d.sync += self.of.copy(self.out_of)
365 m.d.sync += self.z.copy(self.out_z)
366 with m.If(~self.out_norm):
367 m.next = "normalise_2"
368
369
370 class FPNorm2Mod:
371
372 def __init__(self, width):
373 self.out_norm = Signal(reset_less=True)
374 self.in_z = FPNumBase(width, False)
375 self.out_z = FPNumBase(width, False)
376 self.in_of = Overflow()
377 self.out_of = Overflow()
378
379 def setup(self, m, in_z, out_z, in_of, out_of, out_norm):
380 """ links module to inputs and outputs
381 """
382 m.d.comb += self.in_z.copy(in_z)
383 m.d.comb += out_z.copy(self.out_z)
384 m.d.comb += self.in_of.copy(in_of)
385 m.d.comb += out_of.copy(self.out_of)
386 m.d.comb += out_norm.eq(self.out_norm)
387
388 def elaborate(self, platform):
389 m = Module()
390 m.submodules.norm2_in_overflow = self.in_of
391 m.submodules.norm2_out_overflow = self.out_of
392 m.submodules.norm2_in_z = self.in_z
393 m.submodules.norm2_out_z = self.out_z
394 m.d.comb += self.out_z.copy(self.in_z)
395 m.d.comb += self.out_of.copy(self.in_of)
396 m.d.comb += self.out_norm.eq(self.in_z.exp_lt_n126)
397 with m.If(self.out_norm):
398 m.d.comb += [
399 self.out_z.e.eq(self.in_z.e + 1), # INCREASE exponent
400 self.out_z.m.eq(self.in_z.m >> 1), # shift mantissa DOWN
401 self.out_of.guard.eq(self.in_z.m[0]),
402 self.out_of.m0.eq(self.in_z.m[1]),
403 self.out_of.round_bit.eq(self.in_of.guard),
404 self.out_of.sticky.eq(self.in_of.sticky | self.in_of.round_bit)
405 ]
406
407 return m
408
409
410 class FPNorm2(FPState):
411
412 def __init__(self, width):
413 FPState.__init__(self, "normalise_2")
414 self.mod = FPNorm2Mod(width)
415 self.out_norm = Signal(reset_less=True)
416 self.out_z = FPNumBase(width)
417 self.out_of = Overflow()
418
419 def action(self, m):
420 m.d.sync += self.of.copy(self.out_of)
421 m.d.sync += self.z.copy(self.out_z)
422 with m.If(~self.out_norm):
423 m.next = "round"
424
425
426 class FPRoundMod:
427
428 def __init__(self, width):
429 self.in_roundz = Signal(reset_less=True)
430 self.in_z = FPNumBase(width, False)
431 self.out_z = FPNumBase(width, False)
432
433 def setup(self, m, in_z, out_z, in_of):
434 """ links module to inputs and outputs
435 """
436 m.d.comb += self.in_z.copy(in_z)
437 m.d.comb += out_z.copy(self.out_z)
438 m.d.comb += self.in_roundz.eq(in_of.roundz)
439
440 def elaborate(self, platform):
441 m = Module()
442 m.d.comb += self.out_z.copy(self.in_z)
443 with m.If(self.in_roundz):
444 m.d.comb += self.out_z.m.eq(self.in_z.m + 1) # mantissa rounds up
445 with m.If(self.in_z.m == self.in_z.m1s): # all 1s
446 m.d.comb += self.out_z.e.eq(self.in_z.e + 1) # exponent up
447 return m
448
449
450 class FPRound(FPState):
451
452 def __init__(self, width):
453 FPState.__init__(self, "round")
454 self.mod = FPRoundMod(width)
455 self.out_z = FPNumBase(width)
456
457 def action(self, m):
458 m.d.sync += self.z.copy(self.out_z)
459 m.next = "corrections"
460
461
462 class FPCorrectionsMod:
463
464 def __init__(self, width):
465 self.in_z = FPNumOut(width, False)
466 self.out_z = FPNumOut(width, False)
467
468 def setup(self, m, in_z, out_z):
469 """ links module to inputs and outputs
470 """
471 m.d.comb += self.in_z.copy(in_z)
472 m.d.comb += out_z.copy(self.out_z)
473
474 def elaborate(self, platform):
475 m = Module()
476 m.submodules.corr_in_z = self.in_z
477 m.submodules.corr_out_z = self.out_z
478 m.d.comb += self.out_z.copy(self.in_z)
479 with m.If(self.in_z.is_denormalised):
480 m.d.comb += self.out_z.e.eq(self.in_z.N127)
481
482 # with m.If(self.in_z.is_overflowed):
483 # m.d.comb += self.out_z.inf(self.in_z.s)
484 # with m.Else():
485 # m.d.comb += self.out_z.create(self.in_z.s, self.in_z.e, self.in_z.m)
486 return m
487
488
489 class FPCorrections(FPState):
490
491 def __init__(self, width):
492 FPState.__init__(self, "corrections")
493 self.mod = FPCorrectionsMod(width)
494 self.out_z = FPNumBase(width)
495
496 def action(self, m):
497 m.d.sync += self.z.copy(self.out_z)
498 m.next = "pack"
499
500
501 class FPPackMod:
502
503 def __init__(self, width):
504 self.in_z = FPNumOut(width, False)
505 self.out_z = FPNumOut(width, False)
506
507 def setup(self, m, in_z, out_z):
508 """ links module to inputs and outputs
509 """
510 m.d.comb += self.in_z.copy(in_z)
511 m.d.comb += out_z.v.eq(self.out_z.v)
512
513 def elaborate(self, platform):
514 m = Module()
515 m.submodules.pack_in_z = self.in_z
516 with m.If(self.in_z.is_overflowed):
517 m.d.comb += self.out_z.inf(self.in_z.s)
518 with m.Else():
519 m.d.comb += self.out_z.create(self.in_z.s, self.in_z.e, self.in_z.m)
520 return m
521
522
523 class FPPack(FPState):
524
525 def __init__(self, width):
526 FPState.__init__(self, "pack")
527 self.mod = FPPackMod(width)
528 self.out_z = FPNumOut(width, False)
529
530 def action(self, m):
531 m.d.sync += self.z.v.eq(self.out_z.v)
532 m.next = "put_z"
533
534
535 class FPPutZ(FPState):
536
537 def action(self, m):
538 self.put_z(m, self.z, self.out_z, "get_a")
539
540
541 class FPADD:
542
543 def __init__(self, width, single_cycle=False):
544 self.width = width
545 self.single_cycle = single_cycle
546
547 self.in_a = FPOp(width)
548 self.in_b = FPOp(width)
549 self.out_z = FPOp(width)
550
551 self.states = []
552
553 def add_state(self, state):
554 self.states.append(state)
555 return state
556
557 def get_fragment(self, platform=None):
558 """ creates the HDL code-fragment for FPAdd
559 """
560 m = Module()
561
562 # Latches
563 #a = FPNumIn(self.in_a, self.width)
564 b = FPNumIn(self.in_b, self.width)
565 z = FPNumOut(self.width, False)
566
567 m.submodules.fpnum_b = b
568 m.submodules.fpnum_z = z
569
570 w = z.m_width + 4
571 tot = Signal(w, reset_less=True) # sticky/round/guard, {mantissa} result, 1 overflow
572
573 of = Overflow()
574 m.submodules.overflow = of
575
576 geta = self.add_state(FPGetOpA(self.in_a, self.width))
577 #geta.set_inputs({"in_a": self.in_a})
578 #geta.set_outputs({"a": a})
579 a = geta.a
580 # XXX m.d.comb += a.v.eq(self.in_a.v) # links in_a to a
581 m.submodules.fpnum_a = a
582
583 getb = self.add_state(FPGetOpB("get_b"))
584 getb.set_inputs({"in_b": self.in_b})
585 getb.set_outputs({"b": b})
586 # XXX m.d.comb += b.v.eq(self.in_b.v) # links in_b to b
587
588 sc = self.add_state(FPAddSpecialCases(self.width))
589 sc.set_inputs({"a": a, "b": b})
590 sc.set_outputs({"z": z})
591 sc.mod.setup(m, a, b, sc.out_z, sc.out_do_z)
592 m.submodules.specialcases = sc.mod
593
594 dn = self.add_state(FPAddDeNorm("denormalise"))
595 dn.set_inputs({"a": a, "b": b})
596 dn.set_outputs({"a": a, "b": b}) # XXX outputs same as inputs
597
598 if self.single_cycle:
599 alm = self.add_state(FPAddAlignSingle("align"))
600 else:
601 alm = self.add_state(FPAddAlignMulti("align"))
602 alm.set_inputs({"a": a, "b": b})
603 alm.set_outputs({"a": a, "b": b}) # XXX outputs same as inputs
604
605 add0 = self.add_state(FPAddStage0(self.width))
606 add0.set_inputs({"a": a, "b": b})
607 add0.set_outputs({"z": z, "tot": tot})
608 add0.mod.setup(m, a, b, z, add0.out_z, add0.out_tot)
609 m.submodules.add0 = add0.mod
610
611 add1 = self.add_state(FPAddStage1("add_1"))
612 add1.set_inputs({"tot": tot, "z": z}) # Z input passes through
613 add1.set_outputs({"z": z, "of": of}) # XXX Z as output
614
615 n1 = self.add_state(FPNorm1(self.width))
616 n1.set_inputs({"z": z, "of": of}) # XXX Z as output
617 n1.set_outputs({"z": z}) # XXX Z as output
618 n1.mod.setup(m, z, n1.out_z, of, n1.out_of, n1.out_norm)
619 m.submodules.normalise_1 = n1.mod
620
621 n2 = self.add_state(FPNorm2(self.width))
622 n2.set_inputs({"z": n1.out_z, "of": of})
623 n2.set_outputs({"z": z})
624 n2.mod.setup(m, n1.out_z, n2.out_z, of, n2.out_of, n2.out_norm)
625 m.submodules.normalise_2 = n2.mod
626
627 rn = self.add_state(FPRound(self.width))
628 rn.set_inputs({"z": n2.out_z, "of": of})
629 rn.set_outputs({"z": z})
630 rn.mod.setup(m, n2.out_z, rn.out_z, of)
631 m.submodules.roundz = rn.mod
632
633 cor = self.add_state(FPCorrections(self.width))
634 cor.set_inputs({"z": z}) # XXX Z as output
635 cor.set_outputs({"z": z}) # XXX Z as output
636 cor.mod.setup(m, z, cor.out_z)
637 m.submodules.corrections = cor.mod
638
639 pa = self.add_state(FPPack(self.width))
640 pa.set_inputs({"z": z}) # XXX Z as output
641 pa.set_outputs({"z": z}) # XXX Z as output
642 pa.mod.setup(m, z, pa.out_z)
643 m.submodules.pack = pa.mod
644
645 pz = self.add_state(FPPutZ("put_z"))
646 pz.set_inputs({"z": z})
647 pz.set_outputs({"out_z": self.out_z})
648
649 with m.FSM() as fsm:
650
651 for state in self.states:
652 with m.State(state.state_from):
653 state.action(m)
654
655 return m
656
657
658 if __name__ == "__main__":
659 alu = FPADD(width=32)
660 main(alu, ports=alu.in_a.ports() + alu.in_b.ports() + alu.out_z.ports())
661
662
663 # works... but don't use, just do "python fname.py convert -t v"
664 #print (verilog.convert(alu, ports=[
665 # ports=alu.in_a.ports() + \
666 # alu.in_b.ports() + \
667 # alu.out_z.ports())