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 FPModBase
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 FPDivStage0Mod(FPModBase
):
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.
34 def __init__(self
, pspec
):
35 super().__init
__(pspec
, "div0")
38 return FPSCData(self
.pspec
, False)
41 return DivPipeInputData(self
.pspec
)
43 def elaborate(self
, platform
):
47 # mantissas start in the range [1.0, 2.0)
49 # intermediary temp signals
50 is_div
= Signal(reset_less
=True)
51 need_exp_adj
= Signal(reset_less
=True)
53 # "adjusted" - ``self.i.a.rmw`` fractional bits and 2 integer bits
54 adj_a_mw
= self
.i
.a
.rmw
55 adj_a_m
= Signal(self
.i
.a
.rmw
+ 2, reset_less
=True)
56 adj_a_e
= Signal((len(self
.i
.a
.e
), True), reset_less
=True)
58 # adjust (shift) the exponent so that it is even, but only for [r]sqrt
59 comb
+= [is_div
.eq(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)),
60 need_exp_adj
.eq(~is_div
& self
.i
.a
.e
[0]), # even? !div? adjust
61 adj_a_m
.eq(self
.i
.a
.m
<< need_exp_adj
),
62 adj_a_e
.eq(self
.i
.a
.e
- need_exp_adj
)]
64 # adj_a_m now in the range [1.0, 4.0) for sqrt/rsqrt
65 # and [1.0, 2.0) for div
67 fw
= self
.pspec
.core_config
.fract_width
68 divr_rad
= Signal(len(self
.o
.divisor_radicand
), reset_less
=True)
70 # real mantissa fractional widths
74 comb
+= [self
.o
.dividend
.eq(self
.i
.a
.m
<< (fw
*2 - a_mw
)),
75 divr_rad
.eq(Mux(is_div
, self
.i
.b
.m
<< (fw
- b_mw
),
76 adj_a_m
<< (fw
- adj_a_mw
))),
77 self
.o
.divisor_radicand
.eq(divr_rad
),
80 with m
.If(~self
.i
.out_do_z
):
82 with m
.If(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)):
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
))
89 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.SqrtRem
)):
90 comb
+= [self
.o
.z
.e
.eq(adj_a_e
>> 1),
91 self
.o
.z
.s
.eq(self
.i
.a
.s
),
92 self
.o
.operation
.eq(int(DPCOp
.SqrtRem
))
96 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.RSqrtRem
)):
97 comb
+= [self
.o
.z
.e
.eq(-(adj_a_e
>> 1)),
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
)