0629ffb5f539defa9c665b0d2a0023e05238abd0
[ieee754fpu.git] / src / add / fmul.py
1 from nmigen import Module, Signal, Cat, Mux, Array, Const
2 from nmigen.cli import main, verilog
3
4 from fpbase import FPNum, FPOp, Overflow, FPBase
5
6 class FPState(FPBase):
7 def __init__(self, state_from):
8 self.state_from = state_from
9
10 def set_inputs(self, inputs):
11 self.inputs = inputs
12 for k,v in inputs.items():
13 setattr(self, k, v)
14
15 def set_outputs(self, outputs):
16 self.outputs = outputs
17 for k,v in outputs.items():
18 setattr(self, k, v)
19
20 '''
21
22 # OLD DESIGN #
23
24 class FPMUL(FPBase):
25
26 def __init__(self, width):
27 FPBase.__init__(self)
28 self.width = width
29
30 self.in_a = FPOp(width)
31 self.in_b = FPOp(width)
32 self.out_z = FPOp(width)
33
34 def get_fragment(self, platform=None):
35 """ creates the HDL code-fragment for FPMUL
36 """
37 m = Module()
38
39 # Latches
40 a = FPNum(self.width, False)
41 b = FPNum(self.width, False)
42 z = FPNum(self.width, False)
43
44 mw = (z.m_width)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
45 product = Signal(mw)
46
47 of = Overflow()
48
49 with m.FSM() as fsm:
50
51 # ******
52 # gets operand a
53
54 with m.State("get_a"):
55 self.get_op(m, self.in_a, a, "get_b")
56
57 # ******
58 # gets operand b
59
60 with m.State("get_b"):
61 self.get_op(m, self.in_b, b, "special_cases")
62
63 # ******
64 # special cases
65
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()):
69 m.next = "put_z"
70 m.d.sync += z.nan(1)
71 #if a is inf return inf
72 with m.Elif(a.is_inf()):
73 m.next = "put_z"
74 m.d.sync += z.inf(a.s ^ b.s)
75 #if b is zero return NaN
76 with m.If(b.is_zero()):
77 m.d.sync += z.nan(1)
78 #if b is inf return inf
79 with m.Elif(b.is_inf()):
80 m.next = "put_z"
81 m.d.sync += z.inf(a.s ^ b.s)
82 #if a is zero return NaN
83 with m.If(a.is_zero()):
84 m.next = "put_z"
85 m.d.sync += z.nan(1)
86 #if a is zero return zero
87 with m.Elif(a.is_zero()):
88 m.next = "put_z"
89 m.d.sync += z.zero(a.s ^ b.s)
90 #if b is zero return zero
91 with m.Elif(b.is_zero()):
92 m.next = "put_z"
93 m.d.sync += z.zero(a.s ^ b.s)
94 # Denormalised Number checks
95 with m.Else():
96 m.next = "normalise_a"
97 self.denormalise(m, a)
98 self.denormalise(m, b)
99
100 # ******
101 # normalise_a
102
103 with m.State("normalise_a"):
104 self.op_normalise(m, a, "normalise_b")
105
106 # ******
107 # normalise_b
108
109 with m.State("normalise_b"):
110 self.op_normalise(m, b, "multiply_0")
111
112 #multiply_0
113 with m.State("multiply_0"):
114 m.next = "multiply_1"
115 m.d.sync += [
116 z.s.eq(a.s ^ b.s),
117 z.e.eq(a.e + b.e + 1),
118 product.eq(a.m * b.m * 4)
119 ]
120
121 #multiply_1
122 with m.State("multiply_1"):
123 mw = z.m_width
124 m.next = "normalise_1"
125 m.d.sync += [
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)
130 ]
131
132 # ******
133 # First stage of normalisation.
134 with m.State("normalise_1"):
135 self.normalise_1(m, z, of, "normalise_2")
136
137 # ******
138 # Second stage of normalisation.
139
140 with m.State("normalise_2"):
141 self.normalise_2(m, z, of, "round")
142
143 # ******
144 # rounding stage
145
146 with m.State("round"):
147 self.roundz(m, z, of, "corrections")
148
149 # ******
150 # correction stage
151
152 with m.State("corrections"):
153 self.corrections(m, z, "pack")
154
155 # ******
156 # pack stage
157 with m.State("pack"):
158 self.pack(m, z, "put_z")
159
160 # ******
161 # put_z stage
162
163 with m.State("put_z"):
164 self.put_z(m, z, self.out_z, "get_a")
165
166 return m
167
168
169 if __name__ == "__main__":
170 alu = FPMUL(width=32)
171 main(alu, ports=alu.in_a.ports() + alu.in_b.ports() + alu.out_z.ports())
172
173 '''