1 from nmigen
import Module
, Signal
, Cat
, Mux
, Array
, Const
2 from nmigen
.cli
import main
, verilog
4 from ieee754
.fpcommon
.fpbase
import (FPNumIn
, FPNumOut
, FPOpIn
,
5 FPOpOut
, Overflow
, FPBase
, FPState
)
6 from ieee754
.fpcommon
.getop
import FPGetOp
7 from nmutil
.nmoperator
import eq
12 def __init__(self
, width
):
16 self
.in_a
= FPOpIn(width
)
17 self
.in_a
.data_i
= Signal(width
)
18 self
.in_b
= FPOpIn(width
)
19 self
.in_b
.data_i
= Signal(width
)
20 self
.out_z
= FPOpOut(width
)
21 self
.out_z
.data_o
= Signal(width
)
25 def add_state(self
, state
):
26 self
.states
.append(state
)
29 def elaborate(self
, platform
=None):
30 """ creates the HDL code-fragment for FPMUL
35 a
= FPNumIn(None, self
.width
, False)
36 b
= FPNumIn(None, self
.width
, False)
37 z
= FPNumOut(self
.width
, False)
39 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
48 m
.d
.comb
+= a
.v
.eq(self
.in_a
.v
)
49 m
.d
.comb
+= b
.v
.eq(self
.in_b
.v
)
56 with m
.State("get_a"):
57 res
= self
.get_op(m
, self
.in_a
, a
, "get_b")
58 m
.d
.sync
+= eq([a
, self
.in_a
.ready_o
], res
)
63 with m
.State("get_b"):
64 res
= self
.get_op(m
, self
.in_b
, b
, "special_cases")
65 m
.d
.sync
+= eq([b
, self
.in_b
.ready_o
], res
)
70 with m
.State("special_cases"):
71 #if a or b is NaN return NaN
72 with m
.If(a
.is_nan | b
.is_nan
):
75 #if a is inf return inf
76 with m
.Elif(a
.is_inf
):
78 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
79 #if b is zero return NaN
82 #if b is inf return inf
83 with m
.Elif(b
.is_inf
):
85 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
86 #if a is zero return NaN
90 #if a is zero return zero
91 with m
.Elif(a
.is_zero
):
93 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
94 #if b is zero return zero
95 with m
.Elif(b
.is_zero
):
97 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
98 # Denormalised Number checks
100 m
.next
= "normalise_a"
101 self
.denormalise(m
, a
)
102 self
.denormalise(m
, b
)
107 with m
.State("normalise_a"):
108 self
.op_normalise(m
, a
, "normalise_b")
113 with m
.State("normalise_b"):
114 self
.op_normalise(m
, b
, "multiply_0")
117 with m
.State("multiply_0"):
118 m
.next
= "multiply_1"
121 z
.e
.eq(a
.e
+ b
.e
+ 1),
122 product
.eq(a
.m
* b
.m
* 4)
126 with m
.State("multiply_1"):
128 m
.next
= "normalise_1"
130 z
.m
.eq(product
[mw
+2:]),
131 of
.guard
.eq(product
[mw
+1]),
132 of
.round_bit
.eq(product
[mw
]),
133 of
.sticky
.eq(product
[0:mw
] != 0)
137 # First stage of normalisation.
138 with m
.State("normalise_1"):
139 self
.normalise_1(m
, z
, of
, "normalise_2")
142 # Second stage of normalisation.
144 with m
.State("normalise_2"):
145 self
.normalise_2(m
, z
, of
, "round")
150 with m
.State("round"):
151 self
.roundz(m
, z
, of
.roundz
)
152 m
.next
= "corrections"
157 with m
.State("corrections"):
158 self
.corrections(m
, z
, "pack")
162 with m
.State("pack"):
163 self
.pack(m
, z
, "put_z")
168 with m
.State("put_z"):
169 self
.put_z(m
, z
, self
.out_z
, "get_a")
174 if __name__
== "__main__":
175 alu
= FPMUL(width
=32)
176 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())