[Libre-soc-bugs] [Bug 425] DIV overflow not being calculated correctly
bugzilla-daemon at libre-soc.org
bugzilla-daemon at libre-soc.org
Fri Jul 10 10:41:18 BST 2020
https://bugs.libre-soc.org/show_bug.cgi?id=425
--- Comment #7 from Luke Kenneth Casson Leighton <lkcl at lkcl.net> ---
the class that contains the failing code is DivOutputStage.
therefore we need to "get at" DivOutputStage.
the gtkwave tree (and yosys graphvis) show the tree into the failing
code as:
alu -> pipe_end -> output_stage
the classes/instances are:
alu=DIVBasePipe -> pipe_end=DivStagesEnd -> div_out=DivOutputStage
div_out is local therefore i am committing a change which makes it
accessible:
+++ b/src/soc/fu/div/pipeline.py
@@ -34,6 +34,7 @@ class DivStagesEnd(PipeModBaseChain):
core_final = DivCoreFinalStage(self.pspec)
div_out = DivOutputStage(self.pspec)
alu_out = DivMulOutputStage(self.pspec)
+ self.div_out = div_out # debugging - bug #425
return [core_final, div_out, alu_out]
commit f11ffd6b4be87763d7b93a77215212e1004f76e3 (HEAD -> master)
Author: Luke Kenneth Casson Leighton <lkcl at lkcl.net>
Date: Fri Jul 10 10:16:28 2020 +0100
add debugging chain for #425
now we can look at that, back in fu/div/test/test_pipe_caller.py:
vld = yield alu.n.valid_o
while not vld:
yield
vld = yield alu.n.valid_o
print ("bug track", alu.pipe_end.div_out)
yield
this has to be printed out *during* that analysis because it's a pipeline,
and if we leave the inspection too late the data is gone.
after valid_o has dropped is.... too late.
ok so running the test with that, outputted lots of copies of the
DivOutputStage object. now for something more useful:
vld = yield alu.n.valid_o
while not vld:
yield
vld = yield alu.n.valid_o
# bug #425 investigation
do = alu.pipe_end.div_out
dive_abs_ov32 = yield do.i.dive_abs_ov32
quotient_neg = yield do.quotient_neg
print ("dive_abs_ov32", hex(dive_abs_ov32))
print ("quotient_neg", hex(quotient_neg))
yield
that outputs this:
dive_abs_ov32 0x0
quotient_neg 0x1
dive_abs_ov32 0x0
quotient_neg 0x1
ok let's add some more:
# bug #425 investigation
do = alu.pipe_end.div_out
ctx_op = do.i.ctx.op
is_32bit = yield ctx_op.is_32bit
is_signed = yield ctx_op.is_signed
quotient_root = yield do.i.core.quotient_root
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 ("div_by_zero", hex(div_by_zero))
print ("dive_abs_ov32", hex(dive_abs_ov32))
print ("quotient_neg", hex(quotient_neg))
print ("")
committed with this:
commit 1040fedb60ba617b0a85997330c10e5769c06051 (HEAD -> master, origin/master)
Author: Luke Kenneth Casson Leighton <lkcl at lkcl.net>
Date: Fri Jul 10 10:40:15 2020 +0100
add more debug output for #425
and we get this output:
32bit 0x1
signed 0x1
quotient_root 0xfc00000000000003
div_by_zero 0x0
dive_abs_ov32 0x0
quotient_neg 0x1
so that's 32-bit, and signed. therefore sign_bit_mask is 0x8000000.
therefore, 0xfc0000000000003 > 0x8000000 is successful.
therefore, overflow is indicated when it should *not* be indicated.
what i therefore suspect is that when op.is_32bit is set, the top
bits of abs_quotient (quotient_root) must be ignored. but that
dive_abs_ov32 obviously should not.
the relevant code in microwatt divide.vhdl is here:
if is_32bit = '0' then
did_ovf <= overflow or (is_signed and (sresult(64) xor
sresult(63)));
elsif is_signed = '1' then
if ovf32 = '1' or sresult(32) /= sresult(31) then
did_ovf <= '1';
end if;
else
did_ovf <= ovf32;
end if;
where it can be seen that they XOR bit 64 and 63 for 64-bit overflow
detection in the signed case
and for 32-bit overflow, bit 32 and 31 are (effectively) XORed together.
i'm going to give that a shot, see what happens (translate microwatt
overflow detection into nmigen)
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the libre-soc-bugs
mailing list