1 """IEEE 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
12 from nmigen
import Module
, Signal
, Cat
13 from nmigen
.cli
import main
, verilog
15 from nmutil
.pipemodbase
import PipeModBase
16 from ieee754
.fpcommon
.postcalc
import FPPostCalcData
17 from ieee754
.div_rem_sqrt_rsqrt
.div_pipe
import DivPipeOutputData
20 class FPDivPostToFPFormat(PipeModBase
):
21 """ Last stage of div: preparation for normalisation.
23 NOTE: this phase does NOT do ACTUAL DIV processing, it ONLY
24 does "conversion" *out* of the Q/REM last stage
27 def __init__(self
, pspec
):
28 super().__init
__(pspec
, "post_to_fp_fmt")
31 return DivPipeOutputData(self
.pspec
) # Q/Rem in...
34 # XXX REQUIRED. MUST NOT BE CHANGED. this is the format
35 # required for ongoing processing (normalisation, correction etc.)
36 return FPPostCalcData(self
.pspec
) # out to post-process
38 def elaborate(self
, platform
):
42 # copies sign and exponent and mantissa (mantissa and exponent to be
44 comb
+= self
.o
.z
.eq(self
.i
.z
)
46 # Operations and input/output mantissa ranges:
60 with m
.If(~self
.i
.out_do_z
):
61 # following section partially normalizes result to range [1.0, 2.0)
62 fw
= self
.pspec
.core_config
.fract_width
63 qr_int_part
= Signal(2, reset_less
=True)
64 comb
+= qr_int_part
.eq(self
.i
.quotient_root
[fw
:][:2])
66 need_shift
= Signal(reset_less
=True)
68 # shift left when result is less than 2.0 since result_m has 1 more
69 # fraction bit, making assigning to it the equivalent of
71 # this all comes out to:
72 # if quotient_root < 2.0:
73 # # div by 2 from assign; mul by 2 from shift left
74 # result = (quotient_root * 2) / 2
76 # # div by 2 from assign
77 # result = quotient_root / 2
78 comb
+= need_shift
.eq(qr_int_part
< 2)
80 # one extra fraction bit to accommodate the result when not
81 # shifting and for effective div by 2
82 result_m_fract_width
= fw
+ 1
83 # 1 integer bit since the numbers are less than 2.0
84 result_m
= Signal(1 + result_m_fract_width
, reset_less
=True)
85 result_e
= Signal(len(self
.i
.z
.e
), reset_less
=True)
88 result_m
.eq(self
.i
.quotient_root
<< need_shift
),
89 result_e
.eq(self
.i
.z
.e
+ (1 - need_shift
))
92 # result_m is now in the range [1.0, 2.0)
94 self
.o
.z
.m
.eq(result_m
[3:]), # mantissa
95 self
.o
.of
.m0
.eq(result_m
[3]), # copy of mantissa LSB
96 self
.o
.of
.guard
.eq(result_m
[2]), # guard
97 self
.o
.of
.round_bit
.eq(result_m
[1]), # round
98 self
.o
.of
.sticky
.eq(result_m
[0] | self
.i
.remainder
.bool()),
99 self
.o
.z
.e
.eq(result_e
),
102 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
103 comb
+= self
.o
.oz
.eq(self
.i
.oz
)
104 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)