5bd0a3a816eaa53b50396f1ac4cc792c26cc4202
1 # IEEE Floating Point Multiplier
3 from nmigen
import Module
, Signal
, Cat
, Mux
, Elaboratable
4 from nmigen
.lib
.coding
import PriorityEncoder
5 from nmigen
.cli
import main
, verilog
8 from nmutil
.singlepipe
import (StageChain
, SimpleHandshake
)
10 from ieee754
.fpcommon
.fpbase
import (Overflow
, OverflowMod
,
11 FPNumBase
, FPNumBaseRecord
)
12 from ieee754
.fpcommon
.fpbase
import MultiShiftRMerge
13 from ieee754
.fpcommon
.fpbase
import FPState
14 from ieee754
.fpcommon
.getop
import FPPipeContext
17 from ieee754
.fpcommon
.fpbase
import FPState
18 from ieee754
.fpcommon
.denorm
import FPSCData
19 from ieee754
.fpcommon
.postcalc
import FPAddStage1Data
22 class FPAlignModSingle(Elaboratable
):
24 def __init__(self
, pspec
, e_extra
=False):
26 self
.e_extra
= e_extra
31 return FPSCData(self
.pspec
, False)
34 return FPSCData(self
.pspec
, False)
36 def setup(self
, m
, i
):
37 """ links module to inputs and outputs
39 m
.submodules
.align
= self
40 m
.d
.comb
+= self
.i
.eq(i
)
45 def elaborate(self
, platform
):
48 mwid
= self
.o
.z
.m_width
49 pe_a
= PriorityEncoder(mwid
)
50 pe_b
= PriorityEncoder(mwid
)
51 m
.submodules
.norm_pe_a
= pe_a
52 m
.submodules
.norm_pe_b
= pe_b
54 self
.o
.a
.m
.name
= "o_a_m"
55 self
.o
.b
.m
.name
= "o_b_m"
57 m
.submodules
.norm1_insel_a
= insel_a
= FPNumBase(self
.i
.a
)
58 m
.submodules
.norm1_insel_b
= insel_b
= FPNumBase(self
.i
.b
)
59 insel_a
.m
.name
= "i_a_m"
60 insel_b
.m
.name
= "i_b_m"
62 # copy input to output (overridden below)
63 m
.d
.comb
+= self
.o
.eq(self
.i
)
65 # normalisation increase/decrease conditions
66 decrease_a
= Signal(reset_less
=True)
67 decrease_b
= Signal(reset_less
=True)
68 m
.d
.comb
+= decrease_a
.eq(insel_a
.m_msbzero
)
69 m
.d
.comb
+= decrease_b
.eq(insel_b
.m_msbzero
)
71 # ok this is near-identical to FPNorm. TODO: modularise
72 with m
.If(~self
.i
.out_do_z
):
73 with m
.If(decrease_a
):
74 # *sigh* not entirely obvious: count leading zeros (clz)
75 # with a PriorityEncoder: to find from the MSB
76 # we reverse the order of the bits.
77 temp_a
= Signal(mwid
, reset_less
=True)
78 clz_a
= Signal((len(insel_a
.e
), True), reset_less
=True)
80 pe_a
.i
.eq(insel_a
.m
[::-1]), # inverted
81 clz_a
.eq(pe_a
.o
), # count zeros from MSB down
82 temp_a
.eq((insel_a
.m
<< clz_a
)), # shift mantissa UP
83 self
.o
.a
.e
.eq(insel_a
.e
- clz_a
), # DECREASE exponent
84 self
.o
.a
.m
.eq(temp_a
),
87 with m
.If(decrease_b
):
88 # *sigh* not entirely obvious: count leading zeros (clz)
89 # with a PriorityEncoder: to find from the MSB
90 # we reverse the order of the bits.
91 temp_b
= Signal(mwid
, reset_less
=True)
92 clz_b
= Signal((len(insel_b
.e
), True), reset_less
=True)
94 pe_b
.i
.eq(insel_b
.m
[::-1]), # inverted
95 clz_b
.eq(pe_b
.o
), # count zeros from MSB down
96 temp_b
.eq((insel_b
.m
<< clz_b
)), # shift mantissa UP
97 self
.o
.b
.e
.eq(insel_b
.e
- clz_b
), # DECREASE exponent
98 self
.o
.b
.m
.eq(temp_b
),
101 #m.d.comb += self.o.roundz.eq(of.roundz_out)
102 #m.d.comb += self.o.ctx.eq(self.i.ctx)
103 #m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
104 #m.d.comb += self.o.oz.eq(self.i.oz)