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
, FPState
5 from fpcommon
.getop
import FPGetOp
6 from singlepipe
import eq
11 def __init__(self
, width
):
15 self
.in_a
= FPOp(width
)
16 self
.in_b
= FPOp(width
)
17 self
.out_z
= FPOp(width
)
21 def add_state(self
, state
):
22 self
.states
.append(state
)
25 def get_fragment(self
, platform
=None):
26 """ creates the HDL code-fragment for FPMUL
31 a
= FPNumIn(None, self
.width
, False)
32 b
= FPNumIn(None, self
.width
, False)
33 z
= FPNumOut(self
.width
, False)
35 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
44 m
.d
.comb
+= a
.v
.eq(self
.in_a
.v
)
45 m
.d
.comb
+= b
.v
.eq(self
.in_b
.v
)
52 with m
.State("get_a"):
53 res
= self
.get_op(m
, self
.in_a
, a
, "get_b")
54 m
.d
.sync
+= eq([a
, self
.in_a
.ack
], res
)
59 with m
.State("get_b"):
60 res
= self
.get_op(m
, self
.in_b
, b
, "special_cases")
61 m
.d
.sync
+= eq([b
, self
.in_b
.ack
], res
)
66 with m
.State("special_cases"):
67 #if a or b is NaN return NaN
68 with m
.If(a
.is_nan | b
.is_nan
):
71 #if a is inf return inf
72 with m
.Elif(a
.is_inf
):
74 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
75 #if b is zero return NaN
78 #if b is inf return inf
79 with m
.Elif(b
.is_inf
):
81 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
82 #if a is zero return NaN
86 #if a is zero return zero
87 with m
.Elif(a
.is_zero
):
89 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
90 #if b is zero return zero
91 with m
.Elif(b
.is_zero
):
93 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
94 # Denormalised Number checks
96 m
.next
= "normalise_a"
97 self
.denormalise(m
, a
)
98 self
.denormalise(m
, b
)
103 with m
.State("normalise_a"):
104 self
.op_normalise(m
, a
, "normalise_b")
109 with m
.State("normalise_b"):
110 self
.op_normalise(m
, b
, "multiply_0")
113 with m
.State("multiply_0"):
114 m
.next
= "multiply_1"
117 z
.e
.eq(a
.e
+ b
.e
+ 1),
118 product
.eq(a
.m
* b
.m
* 4)
122 with m
.State("multiply_1"):
124 m
.next
= "normalise_1"
126 z
.m
.eq(product
[mw
+2:]),
127 of
.guard
.eq(product
[mw
+1]),
128 of
.round_bit
.eq(product
[mw
]),
129 of
.sticky
.eq(product
[0:mw
] != 0)
133 # First stage of normalisation.
134 with m
.State("normalise_1"):
135 self
.normalise_1(m
, z
, of
, "normalise_2")
138 # Second stage of normalisation.
140 with m
.State("normalise_2"):
141 self
.normalise_2(m
, z
, of
, "round")
146 with m
.State("round"):
147 self
.roundz(m
, z
, of
.roundz
)
148 m
.next
= "corrections"
153 with m
.State("corrections"):
154 self
.corrections(m
, z
, "pack")
158 with m
.State("pack"):
159 self
.pack(m
, z
, "put_z")
164 with m
.State("put_z"):
165 self
.put_z(m
, z
, self
.out_z
, "get_a")
170 if __name__
== "__main__":
171 alu
= FPMUL(width
=32)
172 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())