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
.a
.eq(insel_a
)
64 m
.d
.comb
+= self
.o
.b
.eq(insel_b
)
66 # normalisation increase/decrease conditions
67 decrease_a
= Signal(reset_less
=True)
68 decrease_b
= Signal(reset_less
=True)
69 m
.d
.comb
+= decrease_a
.eq(insel_a
.m_msbzero
)
70 m
.d
.comb
+= decrease_b
.eq(insel_b
.m_msbzero
)
72 # ok this is near-identical to FPNorm. TODO: modularise
73 with m
.If(~self
.i
.out_do_z
):
74 with m
.If(decrease_a
):
75 # *sigh* not entirely obvious: count leading zeros (clz)
76 # with a PriorityEncoder: to find from the MSB
77 # we reverse the order of the bits.
78 temp_a
= Signal(mwid
, reset_less
=True)
79 clz_a
= Signal((len(insel_a
.e
), True), reset_less
=True)
81 pe_a
.i
.eq(insel_a
.m
[::-1]), # inverted
82 clz_a
.eq(pe_a
.o
), # count zeros from MSB down
83 temp_a
.eq((insel_a
.m
<< clz_a
)), # shift mantissa UP
84 self
.o
.a
.e
.eq(insel_a
.e
- clz_a
), # DECREASE exponent
85 self
.o
.a
.m
.eq(temp_a
),
88 with m
.If(decrease_b
):
89 # *sigh* not entirely obvious: count leading zeros (clz)
90 # with a PriorityEncoder: to find from the MSB
91 # we reverse the order of the bits.
92 temp_b
= Signal(mwid
, reset_less
=True)
93 clz_b
= Signal((len(insel_b
.e
), True), reset_less
=True)
95 pe_b
.i
.eq(insel_b
.m
[::-1]), # inverted
96 clz_b
.eq(pe_b
.o
), # count zeros from MSB down
97 temp_b
.eq((insel_b
.m
<< clz_b
)), # shift mantissa UP
98 self
.o
.b
.e
.eq(insel_b
.e
- clz_b
), # DECREASE exponent
99 self
.o
.b
.m
.eq(temp_b
),
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
)