ebae4fd5367eded67664a7bdeab1d2fb726fa5ed
[ieee754fpu.git] / src / ieee754 / fpmul / mul1.py
1 """IEEE754 Floating Point Multiplier Pipeline
2
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4
5 """
6
7 from nmigen import Module, Signal, Mux
8 from nmigen.cli import main, verilog
9
10 from nmutil.pipemodbase import PipeModBase
11 from ieee754.fpcommon.postcalc import FPPostCalcData
12 from ieee754.fpmul.mul0 import FPMulStage0Data
13
14
15 class FPMulStage1Mod(PipeModBase):
16 """ Second stage of mul: preparation for normalisation.
17 """
18
19 def __init__(self, pspec):
20 super().__init__(pspec, "mul1")
21
22 def ispec(self):
23 return FPMulStage0Data(self.pspec)
24
25 def ospec(self):
26 return FPPostCalcData(self.pspec)
27
28 def elaborate(self, platform):
29 m = Module()
30 comb = m.d.comb
31
32 # copy sign
33 comb += self.o.z.s.eq(self.i.z.s)
34 # results are in the range 0.25 to 0.999999999999
35 # sometimes the MSB will be zero, (0.5 * 0.5 = 0.25 which
36 # in binary is 0b010000) so to compensate for that we have
37 # to shift the mantissa up (and reduce the exponent by 1)
38 p = Signal(len(self.i.product), reset_less=True)
39 msb = Signal(reset_less=True)
40 e = self.o.z.e
41 comb += msb.eq(self.i.product[-1])
42 comb += p.eq(Mux(msb, self.i.product, self.i.product<<1))
43 comb += e.eq(Mux(msb, self.i.z.e, self.i.z.e-1))
44
45 # top bits are mantissa, then guard and round, and the rest of
46 # the product is sticky
47 mw = self.o.z.m_width
48 comb += [
49 self.o.z.m.eq(p[mw+2:]), # mantissa
50 self.o.of.m0.eq(p[mw+2]), # copy of LSB
51 self.o.of.guard.eq(p[mw+1]), # guard
52 self.o.of.round_bit.eq(p[mw]), # round
53 self.o.of.sticky.eq(p[0:mw].bool()) # sticky
54 ]
55
56 comb += self.o.out_do_z.eq(self.i.out_do_z)
57 comb += self.o.oz.eq(self.i.oz)
58 comb += self.o.ctx.eq(self.i.ctx)
59
60 return m