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
, FPGetOp
10 def __init__(self
, width
):
14 self
.in_a
= FPOp(width
)
15 self
.in_b
= FPOp(width
)
16 self
.out_z
= FPOp(width
)
18 def get_fragment(self
, platform
=None):
19 """ creates the HDL code-fragment for FPMUL
24 a
= FPNumIn(None, self
.width
, False)
25 b
= FPNumIn(None, self
.width
, False)
26 z
= FPNumOut(self
.width
, False)
28 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
42 with m
.State("get_a"):
43 self
.get_op(m
, self
.in_a
, a
, "get_b")
48 with m
.State("get_b"):
49 self
.get_op(m
, self
.in_b
, b
, "special_cases")
54 with m
.State("special_cases"):
55 #if a or b is NaN return NaN
56 with m
.If(a
.is_nan | b
.is_nan
):
59 #if a is inf return inf
60 with m
.Elif(a
.is_inf
):
62 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
63 #if b is zero return NaN
66 #if b is inf return inf
67 with m
.Elif(b
.is_inf
):
69 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
70 #if a is zero return NaN
74 #if a is zero return zero
75 with m
.Elif(a
.is_zero
):
77 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
78 #if b is zero return zero
79 with m
.Elif(b
.is_zero
):
81 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
82 # Denormalised Number checks
84 m
.next
= "normalise_a"
85 self
.denormalise(m
, a
)
86 self
.denormalise(m
, b
)
91 with m
.State("normalise_a"):
92 self
.op_normalise(m
, a
, "normalise_b")
97 with m
.State("normalise_b"):
98 self
.op_normalise(m
, b
, "multiply_0")
101 with m
.State("multiply_0"):
102 m
.next
= "multiply_1"
105 z
.e
.eq(a
.e
+ b
.e
+ 1),
106 product
.eq(a
.m
* b
.m
* 4)
110 with m
.State("multiply_1"):
112 m
.next
= "normalise_1"
114 z
.m
.eq(product
[mw
+2:]),
115 of
.guard
.eq(product
[mw
+1]),
116 of
.round_bit
.eq(product
[mw
]),
117 of
.sticky
.eq(product
[0:mw
] != 0)
121 # First stage of normalisation.
122 with m
.State("normalise_1"):
123 self
.normalise_1(m
, z
, of
, "normalise_2")
126 # Second stage of normalisation.
128 with m
.State("normalise_2"):
129 self
.normalise_2(m
, z
, of
, "round")
134 with m
.State("round"):
135 self
.roundz(m
, z
, of
.roundz
)
136 m
.next
= "corrections"
141 with m
.State("corrections"):
142 self
.corrections(m
, z
, "pack")
146 with m
.State("pack"):
147 self
.pack(m
, z
, "put_z")
152 with m
.State("put_z"):
153 self
.put_z(m
, z
, self
.out_z
, "get_a")
158 if __name__
== "__main__":
159 alu
= FPMUL(width
=32)
160 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())