From f1217d82dc5ba2ae3f3ef5dda4d948b867635862 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Mon, 29 Jul 2019 23:23:22 +0100 Subject: [PATCH] tidyup --- src/ieee754/fpdiv/div2.py | 109 ++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/src/ieee754/fpdiv/div2.py b/src/ieee754/fpdiv/div2.py index f8d98f4e..84606ba6 100644 --- a/src/ieee754/fpdiv/div2.py +++ b/src/ieee754/fpdiv/div2.py @@ -12,7 +12,10 @@ from ieee754.div_rem_sqrt_rsqrt.div_pipe import DivPipeOutputData class FPDivStage2Mod(FPState, Elaboratable): - """ Second stage of div: preparation for normalisation. + """ Last stage of div: preparation for normalisation. + + NOTE: this phase does NOT do ACTUAL DIV processing, it ONLY + does "conversion" *out* of the Q/REM last stage """ def __init__(self, pspec): @@ -39,18 +42,11 @@ class FPDivStage2Mod(FPState, Elaboratable): def elaborate(self, platform): m = Module() + comb = m.d.comb # copies sign and exponent and mantissa (mantissa and exponent to be # overridden below) - m.d.comb += self.o.z.eq(self.i.z) - - # TODO: this is "phase 3" of divide (the very end of the pipeline) - # takes the Q and R data (whatever) and performs - # last-stage guard/round/sticky and copies mantissa into z. - # post-processing stages take care of things from that point. - - # NOTE: this phase does NOT do ACTUAL DIV processing, it ONLY - # does "conversion" *out* of the Q/REM last stage + comb += self.o.z.eq(self.i.z) # Operations and input/output mantissa ranges: # fdiv: @@ -66,62 +62,51 @@ class FPDivStage2Mod(FPState, Elaboratable): # radicand [1.0, 4.0) # result (0.5, 1.0] - # following section partially normalizes result to the range [1.0, 2.0) - - qr_int_part = Signal(2, reset_less=True) - m.d.comb += qr_int_part.eq( - self.i.quotient_root[self.pspec.core_config.fract_width:][:2]) - - need_shift = Signal(reset_less=True) - - # shift left when result is less than 2.0 since result_m has 1 more - # fraction bit, making assigning to it the equivalent of dividing by 2. - # this all comes out to: - # if quotient_root < 2.0: - # # div by 2 from assign; mul by 2 from shift left - # result = (quotient_root * 2) / 2 - # else: - # # div by 2 from assign - # result = quotient_root / 2 - m.d.comb += need_shift.eq(qr_int_part < 2) - - # one extra fraction bit to accommodate the result when not shifting - # and for effective div by 2 - result_m_fract_width = self.pspec.core_config.fract_width + 1 - # 1 integer bit since the numbers are less than 2.0 - result_m = Signal(1 + result_m_fract_width, reset_less=True) - result_e = Signal(len(self.i.z.e), reset_less=True) - - m.d.comb += [ - result_m.eq(self.i.quotient_root << need_shift), - result_e.eq(self.i.z.e + (1 - need_shift)) - ] - - # result_m is now in the range [1.0, 2.0) - - # FIXME: below comment block out of date - # NOTE: see FPDivStage0Mod comment. the quotient is assumed - # to be in the range 0.499999-recurring to 1.999998. normalisation - # will take care of that, *however*, it *might* be necessary to - # subtract 1 from the exponent and have one extra bit in the - # mantissa to compensate. this is pretty much exactly what's - # done in FPMUL, due to 0.5-0.9999 * 0.5-0.9999 also producing - # values within the range 0.5 to 1.999998 - # FIXME: above comment block out of date - - with m.If(~self.i.out_do_z): # FIXME: does this need to be conditional? - m.d.comb += [ - self.o.z.m.eq(result_m[3:]), - self.o.of.m0.eq(result_m[3]), # copy of LSB - self.o.of.guard.eq(result_m[2]), - self.o.of.round_bit.eq(result_m[1]), + with m.If(~self.i.out_do_z): + # following section partially normalizes result to range [1.0, 2.0) + fw = self.pspec.core_config.fract_width + qr_int_part = Signal(2, reset_less=True) + comb += qr_int_part.eq(self.i.quotient_root[fw:][:2]) + + need_shift = Signal(reset_less=True) + + # shift left when result is less than 2.0 since result_m has 1 more + # fraction bit, making assigning to it the equivalent of + # dividing by 2. + # this all comes out to: + # if quotient_root < 2.0: + # # div by 2 from assign; mul by 2 from shift left + # result = (quotient_root * 2) / 2 + # else: + # # div by 2 from assign + # result = quotient_root / 2 + comb += need_shift.eq(qr_int_part < 2) + + # one extra fraction bit to accommodate the result when not + # shifting and for effective div by 2 + result_m_fract_width = fw + 1 + # 1 integer bit since the numbers are less than 2.0 + result_m = Signal(1 + result_m_fract_width, reset_less=True) + result_e = Signal(len(self.i.z.e), reset_less=True) + + comb += [ + result_m.eq(self.i.quotient_root << need_shift), + result_e.eq(self.i.z.e + (1 - need_shift)) + ] + + # result_m is now in the range [1.0, 2.0) + comb += [ + self.o.z.m.eq(result_m[3:]), # mantissa + self.o.of.m0.eq(result_m[3]), # copy of mantissa LSB + self.o.of.guard.eq(result_m[2]), # guard + self.o.of.round_bit.eq(result_m[1]), # round self.o.of.sticky.eq(result_m[0] | self.i.remainder.bool()), self.o.z.e.eq(result_e), ] - m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) - m.d.comb += self.o.oz.eq(self.i.oz) - m.d.comb += self.o.ctx.eq(self.i.ctx) + comb += self.o.out_do_z.eq(self.i.out_do_z) + comb += self.o.oz.eq(self.i.oz) + comb += self.o.ctx.eq(self.i.ctx) return m -- 2.30.2