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_b
= FPOpIn(width
)
18 self
.out_z
= FPOpOut(width
)
22 def add_state(self
, state
):
23 self
.states
.append(state
)
26 def elaborate(self
, platform
=None):
27 """ creates the HDL code-fragment for FPMUL
32 a
= FPNumIn(None, self
.width
, False)
33 b
= FPNumIn(None, self
.width
, False)
34 z
= FPNumOut(self
.width
, False)
36 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
45 m
.d
.comb
+= a
.v
.eq(self
.in_a
.v
)
46 m
.d
.comb
+= b
.v
.eq(self
.in_b
.v
)
53 with m
.State("get_a"):
54 res
= self
.get_op(m
, self
.in_a
, a
, "get_b")
55 m
.d
.sync
+= eq([a
, self
.in_a
.ack
], res
)
60 with m
.State("get_b"):
61 res
= self
.get_op(m
, self
.in_b
, b
, "special_cases")
62 m
.d
.sync
+= eq([b
, self
.in_b
.ack
], res
)
67 with m
.State("special_cases"):
68 #if a or b is NaN return NaN
69 with m
.If(a
.is_nan | b
.is_nan
):
72 #if a is inf return inf
73 with m
.Elif(a
.is_inf
):
75 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
76 #if b is zero return NaN
79 #if b is inf return inf
80 with m
.Elif(b
.is_inf
):
82 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
83 #if a is zero return NaN
87 #if a is zero return zero
88 with m
.Elif(a
.is_zero
):
90 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
91 #if b is zero return zero
92 with m
.Elif(b
.is_zero
):
94 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
95 # Denormalised Number checks
97 m
.next
= "normalise_a"
98 self
.denormalise(m
, a
)
99 self
.denormalise(m
, b
)
104 with m
.State("normalise_a"):
105 self
.op_normalise(m
, a
, "normalise_b")
110 with m
.State("normalise_b"):
111 self
.op_normalise(m
, b
, "multiply_0")
114 with m
.State("multiply_0"):
115 m
.next
= "multiply_1"
118 z
.e
.eq(a
.e
+ b
.e
+ 1),
119 product
.eq(a
.m
* b
.m
* 4)
123 with m
.State("multiply_1"):
125 m
.next
= "normalise_1"
127 z
.m
.eq(product
[mw
+2:]),
128 of
.guard
.eq(product
[mw
+1]),
129 of
.round_bit
.eq(product
[mw
]),
130 of
.sticky
.eq(product
[0:mw
] != 0)
134 # First stage of normalisation.
135 with m
.State("normalise_1"):
136 self
.normalise_1(m
, z
, of
, "normalise_2")
139 # Second stage of normalisation.
141 with m
.State("normalise_2"):
142 self
.normalise_2(m
, z
, of
, "round")
147 with m
.State("round"):
148 self
.roundz(m
, z
, of
.roundz
)
149 m
.next
= "corrections"
154 with m
.State("corrections"):
155 self
.corrections(m
, z
, "pack")
159 with m
.State("pack"):
160 self
.pack(m
, z
, "put_z")
165 with m
.State("put_z"):
166 self
.put_z(m
, z
, self
.out_z
, "get_a")
171 if __name__
== "__main__":
172 alu
= FPMUL(width
=32)
173 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())