fix broken remainder for div FSM
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 25 Aug 2020 18:54:51 +0000 (11:54 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 25 Aug 2020 18:54:51 +0000 (11:54 -0700)
src/soc/fu/div/fsm.py
src/soc/fu/div/test/test_pipe_caller.py

index befb463d0ef1f23fcbde6933e0c0e9070cf08b3f..a761dfbc3645e0038818a12525d640731ddd5a56 100644 (file)
@@ -171,7 +171,13 @@ class FSMDivCoreStage(ControlBase):
 
         m.d.comb += data_o.eq_without_core(self.saved_input_data)
         m.d.comb += core_o.quotient_root.eq(self.div_state_next.o.quotient)
-        m.d.comb += core_o.remainder.eq(self.div_state_next.o.remainder)
+        # fract width of `DivPipeCoreOutputData.remainder`
+        remainder_fract_width = 64 * 3
+        # fract width of `DivPipeCoreInputData.dividend`
+        dividend_fract_width = 64 * 2
+        rem_start = remainder_fract_width - dividend_fract_width
+        m.d.comb += core_o.remainder.eq(self.div_state_next.o.remainder
+                                        << rem_start)
         m.d.comb += self.n.valid_o.eq(~self.empty & self.div_state_next.o.done)
         m.d.comb += self.p.ready_o.eq(self.empty)
         m.d.sync += self.saved_state.eq(self.div_state_next.o)
index 4fb31567771af5bde6173f46373de09f0c83d837..ee8e5b95ecdff6de3f71e5094f93226b6042a87f 100644 (file)
@@ -11,6 +11,24 @@ from soc.fu.div.test.helper import (log_rand, get_cu_inputs,
 
 
 class DivTestCases(TestAccumulatorBase):
+    def case_divw_regression(self):
+        # simulator is wrong, FSM and power-instruction-analyzer are both correct
+        lst = [f"divw 0, 1, 2"]
+        initial_regs = [0] * 32
+        initial_regs[2] = 0x2
+        initial_regs[1] = 0x80000000
+        with Program(lst, bigendian) as prog:
+            self.add_case(prog, initial_regs)
+
+    # modulo
+    def case_modsd_regression2(self):
+        lst = [f"modsd 0, 1, 2"]
+        initial_regs = [0] * 32
+        initial_regs[2] = 0xff
+        initial_regs[1] = 0x7fffffffffffffff
+        with Program(lst, bigendian) as prog:
+            self.add_case(prog, initial_regs)
+
     # modulo
     def case_modsd_regression(self):
         lst = [f"modsd 17, 27, 0"]