switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / fpdiv / div0.py
1 """IEEE754 Floating Point Divider / Square-Root / Reciprocal-Square-Root
2
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 Copyright (C) 2019 Jacob Lifshay
5
6 Relevant bugreports:
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
10
11 """
12
13 from nmigen import Module, Signal, Cat, Elaboratable, Const, Mux
14 from nmigen.cli import main, verilog
15
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
22
23
24 class FPDivPreFPAdjust(PipeModBase):
25 """ DIV/SQRT/RSQRT "preparation" module.
26
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.
30
31 no *actual* processing occurs here: it is *purely* preparation work.
32 """
33 def __init__(self, pspec):
34 super().__init__(pspec, "pre_fp_adjust")
35
36 def ispec(self):
37 return FPSCData(self.pspec, False)
38
39 def ospec(self):
40 return DivPipeInputData(self.pspec)
41
42 def elaborate(self, platform):
43 m = Module()
44 comb = m.d.comb
45
46 # mantissas start in the range [1.0, 2.0)
47
48 # intermediary temp signals
49 is_div = Signal(reset_less=True)
50 need_exp_adj = Signal(reset_less=True)
51
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)
56
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)]
62
63 # adj_a_m now in the range [1.0, 4.0) for sqrt/rsqrt
64 # and [1.0, 2.0) for div
65
66 fw = self.pspec.core_config.fract_width
67 divr_rad = Signal(len(self.o.divisor_radicand), reset_less=True)
68
69 # real mantissa fractional widths
70 a_mw = self.i.a.rmw
71 b_mw = self.i.b.rmw
72
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),
77 ]
78
79 ############# DIV #############
80 with m.If(self.i.ctx.op == int(DPCOp.UDivRem)):
81 # DIV: subtract exponents, XOR sign
82 comb += [self.o.z.e.eq(self.i.a.e - self.i.b.e),
83 self.o.z.s.eq(self.i.a.s ^ self.i.b.s),
84 self.o.operation.eq(int(DPCOp.UDivRem))
85 ]
86
87 ############# SQRT #############
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))
93 ]
94
95 ############# RSQRT #############
96 with m.Elif(self.i.ctx.op == int(DPCOp.RSqrtRem)):
97 # RSQRT: sign same, [adjusted] exponent halved and inverted
98 comb += [self.o.z.e.eq(-(adj_a_e >> 1)), # NEGATE and halve
99 self.o.z.s.eq(self.i.a.s),
100 self.o.operation.eq(int(DPCOp.RSqrtRem))
101 ]
102
103 # pass through context
104 comb += self.o.oz.eq(self.i.oz)
105 comb += self.o.out_do_z.eq(self.i.out_do_z)
106 comb += self.o.ctx.eq(self.i.ctx)
107
108 return m
109
110