bb508e1a4733b61427c688d3d9488dee9c5f490c
1 from nmigen
import Module
, Signal
2 from nmigen
.cli
import main
, verilog
4 from fpbase
import FPNum
, FPOp
, Overflow
, FPBase
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
= FPNum(self
.width
, False)
24 b
= FPNum(self
.width
, False)
25 z
= FPNum(self
.width
, False)
27 mw
= (z
.m_width
)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
37 with m
.State("get_a"):
38 self
.get_op(m
, self
.in_a
, a
, "get_b")
43 with m
.State("get_b"):
44 self
.get_op(m
, self
.in_b
, b
, "special_cases")
49 with m
.State("special_cases"):
50 #if a or b is NaN return NaN
51 with m
.If(a
.is_nan() | b
.is_nan()):
54 #if a is inf return inf
55 with m
.Elif(a
.is_inf()):
57 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
58 #if b is zero return NaN
59 with m
.If(b
.is_zero()):
61 #if b is inf return inf
62 with m
.Elif(b
.is_inf()):
64 m
.d
.sync
+= z
.inf(a
.s ^ b
.s
)
65 #if a is zero return NaN
66 with m
.If(a
.is_zero()):
69 #if a is zero return zero
70 with m
.Elif(a
.is_zero()):
72 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
73 #if b is zero return zero
74 with m
.Elif(b
.is_zero()):
76 m
.d
.sync
+= z
.zero(a
.s ^ b
.s
)
77 # Denormalised Number checks
79 m
.next
= "normalise_a"
80 self
.denormalise(m
, a
)
81 self
.denormalise(m
, b
)
86 with m
.State("normalise_a"):
87 self
.op_normalise(m
, a
, "normalise_b")
92 with m
.State("normalise_b"):
93 self
.op_normalise(m
, b
, "multiply_0")
96 with m
.State("multiply_0"):
100 z
.e
.eq(a
.e
+ b
.e
+ 1),
101 product
.eq(a
.m
* b
.m
* 4)
105 with m
.State("multiply_1"):
107 m
.next
= "normalise_1"
109 z
.m
.eq(product
[mw
+3:]),
110 of
.guard
.eq(product
[mw
+2]),
111 of
.round_bit
.eq(product
[mw
+1]),
112 of
.sticky
.eq(product
[0:mw
] != 0)
116 # First stage of normalisation.
117 with m
.State("normalise_1"):
118 self
.normalise_1(m
, z
, of
, "normalise_2")
121 # Second stage of normalisation.
123 with m
.State("normalise_2"):
124 self
.normalise_2(m
, z
, of
, "round")
129 with m
.State("round"):
130 self
.roundz(m
, z
, of
, "corrections")
135 with m
.State("corrections"):
136 self
.corrections(m
, z
, "pack")
140 with m
.State("pack"):
141 self
.pack(m
, z
, "put_z")
146 with m
.State("put_z"):
147 self
.put_z(m
, z
, self
.out_z
, "get_a")
154 //if a is NaN or b is NaN return NaN
155 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
161 //if a is inf return inf
162 end else if (a_e == 128) begin
166 //if b is zero return NaN
167 if (($signed(b_e) == -127) && (b_m == 0)) begin
174 //if b is inf return inf
175 end else if (b_e == 128) begin
179 //if a is zero return NaN
180 if (($signed(a_e) == -127) && (a_m == 0)) begin
187 //if a is zero return zero
188 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
193 //if b is zero return zero
194 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
201 //Denormalised Number
202 if ($signed(a_e) == -127) begin
207 //Denormalised Number
208 if ($signed(b_e) == -127) begin
213 state <= normalise_a;
220 state <= normalise_b;
240 z_e <= a_e + b_e + 1;
241 product <= a_m * b_m * 4;
247 z_m <= product[49:26];
248 guard <= product[25];
249 round_bit <= product[24];
250 sticky <= (product[23:0] != 0);
251 state <= normalise_1;
256 if (z_m[23] == 0) begin
263 state <= normalise_2;
269 if ($signed(z_e) < -126) begin
274 sticky <= sticky | round_bit;
282 if (guard && (round_bit | sticky | z_m[0])) begin
284 if (z_m == 24'hffffff) begin
293 z[22 : 0] <= z_m[22:0];
294 z[30 : 23] <= z_e[7:0] + 127;
296 if ($signed(z_e) == -126 && z_m[23] == 0) begin
301 if ($signed(z_e) > 127) begin
313 if (s_output_z_stb && output_z_ack) begin
321 if __name__
== "__main__":
322 alu
= FPMUL(width
=32)
323 main(alu
, ports
=alu
.in_a
.ports() + alu
.in_b
.ports() + alu
.out_z
.ports())