rename FPModBase* to PipeModBase*
[ieee754fpu.git] / src / ieee754 / fpdiv / div0.py
1 """IEEE754 Floating Point Divider
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 FPDivStage0Mod(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
34 def __init__(self, pspec):
35 super().__init__(pspec, "div0")
36
37 def ispec(self):
38 return FPSCData(self.pspec, False)
39
40 def ospec(self):
41 return DivPipeInputData(self.pspec)
42
43 def elaborate(self, platform):
44 m = Module()
45 comb = m.d.comb
46
47 # mantissas start in the range [1.0, 2.0)
48
49 # intermediary temp signals
50 is_div = Signal(reset_less=True)
51 need_exp_adj = Signal(reset_less=True)
52
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)
57
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)]
63
64 # adj_a_m now in the range [1.0, 4.0) for sqrt/rsqrt
65 # and [1.0, 2.0) for div
66
67 fw = self.pspec.core_config.fract_width
68 divr_rad = Signal(len(self.o.divisor_radicand), reset_less=True)
69
70 # real mantissa fractional widths
71 a_mw = self.i.a.rmw
72 b_mw = self.i.b.rmw
73
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),
78 ]
79
80 with m.If(~self.i.out_do_z):
81 # DIV
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))
86 ]
87
88 # SQRT
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))
93 ]
94
95 # RSQRT
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))
100 ]
101
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)
106
107 return m
108
109