1 from nmigen
import Module
, Signal
, Cat
, Mux
, Array
, Const
2 from nmigen
.cli
import main
, verilog
4 from fpbase
import FPNumIn
, FPNumOut
, FPOp
, Overflow
, FPBase
5 from nmigen_add_experiment
import FPState
9 def __init__(self
, width
):
13 self
.in_a
= FPOp(width
)
14 self
.in_b
= FPOp(width
)
15 self
.out_z
= FPOp(width
)
17 def get_fragment(self
, platform
=None):
18 """ creates the HDL code-fragment for FPMUL
23 a
= FPNumIn(None, self
.width
, False)
24 b
= FPNumIn(None, self
.width
, False)
25 z
= FPNumOut(self
.width
, False)
27 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
41 with m
.State("get_a"):
42 self
.get_op(m
, self
.in_a
, a
, "get_b")
47 with m
.State("get_b"):
48 self
.get_op(m
, self
.in_b
, b
, "special_cases")
53 with m
.State("special_cases"):
54 #if a or b is NaN return NaN
55 with m
.If(a
.is_nan | b
.is_nan
):
58 #if a is inf return inf
59 with m
.Elif(a
.is_inf
):
61 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
62 #if b is zero return NaN
65 #if b is inf return inf
66 with m
.Elif(b
.is_inf
):
68 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
69 #if a is zero return NaN
73 #if a is zero return zero
74 with m
.Elif(a
.is_zero
):
76 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
77 #if b is zero return zero
78 with m
.Elif(b
.is_zero
):
80 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
81 # Denormalised Number checks
83 m
.next
= "normalise_a"
84 self
.denormalise(m
, a
)
85 self
.denormalise(m
, b
)
90 with m
.State("normalise_a"):
91 self
.op_normalise(m
, a
, "normalise_b")
96 with m
.State("normalise_b"):
97 self
.op_normalise(m
, b
, "multiply_0")
100 with m
.State("multiply_0"):
101 m
.next
= "multiply_1"
104 z
.e
.eq(a
.e
+ b
.e
+ 1),
105 product
.eq(a
.m
* b
.m
* 4)
109 with m
.State("multiply_1"):
111 m
.next
= "normalise_1"
113 z
.m
.eq(product
[mw
+2:]),
114 of
.guard
.eq(product
[mw
+1]),
115 of
.round_bit
.eq(product
[mw
]),
116 of
.sticky
.eq(product
[0:mw
] != 0)
120 # First stage of normalisation.
121 with m
.State("normalise_1"):
122 self
.normalise_1(m
, z
, of
, "normalise_2")
125 # Second stage of normalisation.
127 with m
.State("normalise_2"):
128 self
.normalise_2(m
, z
, of
, "round")
133 with m
.State("round"):
134 self
.roundz(m
, z
, of
.roundz
)
135 m
.next
= "corrections"
140 with m
.State("corrections"):
141 self
.corrections(m
, z
, "pack")
145 with m
.State("pack"):
146 self
.pack(m
, z
, "put_z")
151 with m
.State("put_z"):
152 self
.put_z(m
, z
, self
.out_z
, "get_a")
157 if __name__
== "__main__":
158 alu
= FPMUL(width
=32)
159 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())