From: Luke Kenneth Casson Leighton Date: Fri, 10 Jul 2020 13:12:50 +0000 (+0100) Subject: add test7 div regression X-Git-Tag: div_pipeline~110 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7c7e005ee8ca4d3f008573fded47a3a74a86739b;p=soc.git add test7 div regression --- diff --git a/src/soc/fu/div/output_stage.py b/src/soc/fu/div/output_stage.py index 80968ea5..6b5a42ec 100644 --- a/src/soc/fu/div/output_stage.py +++ b/src/soc/fu/div/output_stage.py @@ -23,7 +23,7 @@ class DivOutputStage(PipeModBase): self.fields.create_specs() self.quotient_neg = Signal() self.remainder_neg = Signal() - self.quotient_64 = Signal(64) + self.quotient_65 = Signal(65) # one extra spare bit for overflow self.remainder_64 = Signal(64) def ispec(self): @@ -48,7 +48,7 @@ class DivOutputStage(PipeModBase): abs_remainder = self.i.core.remainder[rem_start:rem_start+64] dividend_neg = self.i.dividend_neg divisor_neg = self.i.divisor_neg - quotient_64 = self.quotient_64 + quotient_65 = self.quotient_65 remainder_64 = self.remainder_64 # work out if sign of result is to be negative @@ -61,7 +61,7 @@ class DivOutputStage(PipeModBase): # result as negation of just the lower 32-bits, so we don't # need to do anything special before negating comb += [ - quotient_64.eq(Mux(self.quotient_neg, + quotient_65.eq(Mux(self.quotient_neg, -abs_quotient, abs_quotient)), remainder_64.eq(Mux(self.remainder_neg, -abs_remainder, abs_remainder)) @@ -92,6 +92,22 @@ class DivOutputStage(PipeModBase): with m.Else(): calc_overflow(self.i.dive_abs_ov64, 0x8000000000000000) + # microwatt overflow detection + ov = Signal(reset_less=True) + with m.If(self.i.div_by_zero): + comb += ov.eq(1) + with m.Elif(~op.is_32bit): + comb += ov.eq(self.i.dive_abs_ov64) + with m.If(op.is_signed & (quotient_65[64] ^ quotient_65[63])): + comb += ov.eq(1) + with m.Elif(op.is_signed): + comb += ov.eq(self.i.dive_abs_ov32) + with m.If(quotient_65[32] != quotient_65[31]): + comb += ov.eq(1) + with m.Else(): + comb += ov.eq(self.i.dive_abs_ov32) + comb += xer_ov.eq(Repl(ov, 2)) # set OV _and_ OV32 + ########################## # main switch for DIV @@ -102,20 +118,20 @@ class DivOutputStage(PipeModBase): with m.If(op.is_32bit): with m.If(op.is_signed): # matches POWER9's divweo behavior - comb += o.eq(quotient_64[0:32].as_unsigned()) + comb += o.eq(quotient_65[0:32].as_unsigned()) with m.Else(): - comb += o.eq(quotient_64[0:32].as_unsigned()) + comb += o.eq(quotient_65[0:32].as_unsigned()) with m.Else(): - comb += o.eq(quotient_64) + comb += o.eq(quotient_65) with m.Case(InternalOp.OP_DIV): with m.If(op.is_32bit): with m.If(op.is_signed): # matches POWER9's divwo behavior - comb += o.eq(quotient_64[0:32].as_unsigned()) + comb += o.eq(quotient_65[0:32].as_unsigned()) with m.Else(): - comb += o.eq(quotient_64[0:32].as_unsigned()) + comb += o.eq(quotient_65[0:32].as_unsigned()) with m.Else(): - comb += o.eq(quotient_64) + comb += o.eq(quotient_65) with m.Case(InternalOp.OP_MOD): with m.If(op.is_32bit): with m.If(op.is_signed): diff --git a/src/soc/fu/div/test/test_pipe_caller.py b/src/soc/fu/div/test/test_pipe_caller.py index 9525a337..663bb0ac 100644 --- a/src/soc/fu/div/test/test_pipe_caller.py +++ b/src/soc/fu/div/test/test_pipe_caller.py @@ -132,6 +132,14 @@ class DIVTestCase(FHDLTestCase): initial_regs[2] = 0x9dc66a7622c32bc0 self.run_tst_program(Program(lst), initial_regs) + def test_7_regression(self): + # https://bugs.libre-soc.org/show_bug.cgi?id=425 + lst = ["divw. 3, 1, 2"] + initial_regs = [0] * 32 + initial_regs[1] = 0xf1791627e05e8096 + initial_regs[2] = 0xffc868bf4573da0b + self.run_tst_program(Program(lst), initial_regs) + def tst_rand_divw(self): insns = ["divw", "divw.", "divwo", "divwo."] for i in range(40): @@ -223,12 +231,14 @@ class TestRunner(FHDLTestCase): is_32bit = yield ctx_op.is_32bit is_signed = yield ctx_op.is_signed quotient_root = yield do.i.core.quotient_root + quotient_65 = yield do.quotient_65 dive_abs_ov32 = yield do.i.dive_abs_ov32 div_by_zero = yield do.i.div_by_zero quotient_neg = yield do.quotient_neg print ("32bit", hex(is_32bit)) print ("signed", hex(is_signed)) print ("quotient_root", hex(quotient_root)) + print ("quotient_65", hex(quotient_65)) print ("div_by_zero", hex(div_by_zero)) print ("dive_abs_ov32", hex(dive_abs_ov32)) print ("quotient_neg", hex(quotient_neg))