1 """IEEE754 Floating Point Divider
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 Copyright (C) 2019 Jacob Lifshay
7 * http://bugs.libre-riscv.org/show_bug.cgi?id=99
8 * http://bugs.libre-riscv.org/show_bug.cgi?id=43
9 * http://bugs.libre-riscv.org/show_bug.cgi?id=44
13 from nmigen
import Module
, Signal
, Cat
, Elaboratable
, Const
, Mux
14 from nmigen
.cli
import main
, verilog
16 from nmutil
.pipemodbase
import PipeModBase
17 from ieee754
.fpcommon
.fpbase
import FPNumBaseRecord
18 from ieee754
.fpcommon
.denorm
import FPSCData
19 from ieee754
.fpcommon
.getop
import FPPipeContext
20 from ieee754
.div_rem_sqrt_rsqrt
.div_pipe
import DivPipeInputData
21 from ieee754
.div_rem_sqrt_rsqrt
.core
import DivPipeCoreOperation
as DPCOp
24 class FPDivPreFPAdjust(PipeModBase
):
25 """ DIV/SQRT/RSQRT "preparation" module.
27 adjusts mantissa and exponent (sqrt/rsqrt exponent must be even),
28 puts exponent (and sign) into data structures for passing through to
29 the end, and puts the (adjusted) mantissa into the processing engine.
31 no *actual* processing occurs here: it is *purely* preparation work.
33 def __init__(self
, pspec
):
34 super().__init
__(pspec
, "pre_fp_adjust")
37 return FPSCData(self
.pspec
, False)
40 return DivPipeInputData(self
.pspec
)
42 def elaborate(self
, platform
):
46 # mantissas start in the range [1.0, 2.0)
48 # intermediary temp signals
49 is_div
= Signal(reset_less
=True)
50 need_exp_adj
= Signal(reset_less
=True)
52 # "adjusted" - ``self.i.a.rmw`` fractional bits and 2 integer bits
53 adj_a_mw
= self
.i
.a
.rmw
54 adj_a_m
= Signal(self
.i
.a
.rmw
+ 2, reset_less
=True)
55 adj_a_e
= Signal((len(self
.i
.a
.e
), True), reset_less
=True)
57 # adjust (shift) the exponent so that it is even, but only for [r]sqrt
58 comb
+= [is_div
.eq(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)),
59 need_exp_adj
.eq(~is_div
& self
.i
.a
.e
[0]), # even? !div? adjust
60 adj_a_m
.eq(self
.i
.a
.m
<< need_exp_adj
),
61 adj_a_e
.eq(self
.i
.a
.e
- need_exp_adj
)]
63 # adj_a_m now in the range [1.0, 4.0) for sqrt/rsqrt
64 # and [1.0, 2.0) for div
66 fw
= self
.pspec
.core_config
.fract_width
67 divr_rad
= Signal(len(self
.o
.divisor_radicand
), reset_less
=True)
69 # real mantissa fractional widths
73 comb
+= [self
.o
.dividend
.eq(self
.i
.a
.m
<< (fw
*2 - a_mw
)),
74 divr_rad
.eq(Mux(is_div
, self
.i
.b
.m
<< (fw
- b_mw
),
75 adj_a_m
<< (fw
- adj_a_mw
))),
76 self
.o
.divisor_radicand
.eq(divr_rad
),
79 with m
.If(~self
.i
.out_do_z
):
81 with m
.If(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)):
82 # DIV: subtract exponents, XOR sign
83 comb
+= [self
.o
.z
.e
.eq(self
.i
.a
.e
- self
.i
.b
.e
),
84 self
.o
.z
.s
.eq(self
.i
.a
.s ^ self
.i
.b
.s
),
85 self
.o
.operation
.eq(int(DPCOp
.UDivRem
))
88 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.SqrtRem
)):
89 # SQRT: sign is the same, [adjusted] exponent is halved
90 comb
+= [self
.o
.z
.e
.eq(adj_a_e
>> 1), # halve
91 self
.o
.z
.s
.eq(self
.i
.a
.s
),
92 self
.o
.operation
.eq(int(DPCOp
.SqrtRem
))
95 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.RSqrtRem
)):
96 # RSQRT: sign same, [adjusted] exponent halved and inverted
97 comb
+= [self
.o
.z
.e
.eq(-(adj_a_e
>> 1)), # NEGATE and halve
98 self
.o
.z
.s
.eq(self
.i
.a
.s
),
99 self
.o
.operation
.eq(int(DPCOp
.RSqrtRem
))
102 # these are required and must not be touched
103 comb
+= self
.o
.oz
.eq(self
.i
.oz
)
104 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
105 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)