switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / part_cmp / eq_gt_ge.py
index 7d7e4ccc56c5e6e3c2d8027a4ab662e9f9fe57e0..4cc8a0ef081a43fdc6bb4727f6626a172da58afa 100644 (file)
@@ -3,24 +3,30 @@
 
 """
 Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
 
 dynamically-partitionable "comparison" class, directly equivalent
-to Signal.__eq__ except SIMD-partitionable
+to Signal.__eq__, __gt__ and __ge__, except SIMD-partitionable
 
 See:
 
-* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/eq
+* http://libre-riscv.org/3d_gpu/architecture/dynamic_simd/
 * http://bugs.libre-riscv.org/show_bug.cgi?id=132
+* http://bugs.libre-riscv.org/show_bug.cgi?id=171
 """
 
-from nmigen import Signal, Module, Elaboratable, Cat, C, Mux, Repl
-from nmigen.cli import main
+from nmigen import Signal, Module, Elaboratable, Cat, C
+from nmigen.back.pysim import Simulator, Delay
 
 from ieee754.part_mul_add.partpoints import PartitionPoints
-from ieee754.part_cmp.experiments.gt_combiner import GTCombiner
+from ieee754.part_cmp.gt_combiner import GTCombiner
+from ieee754.part_cmp.reorder_results import ReorderResults
 
 
 class PartitionedEqGtGe(Elaboratable):
+    EQ = C(0b00, 2)
+    GT = C(0b01, 2)
+    GE = C(0b10, 2)
 
     # Expansion of the partitioned equals module to handle Greater
     # Than and Greater than or Equal to. The function being evaluated
@@ -38,14 +44,16 @@ class PartitionedEqGtGe(Elaboratable):
         self.partition_points = PartitionPoints(partition_points)
         self.mwidth = len(self.partition_points)+1
         self.output = Signal(self.mwidth, reset_less=True)
-        if not self.partition_points.fits_in_width(width):
-            raise ValueError("partition_points doesn't fit in width")
+        assert self.partition_points.fits_in_width(width), \
+            "partition_points doesn't fit in width"
 
     def elaborate(self, platform):
         m = Module()
         comb = m.d.comb
         m.submodules.gtc = gtc = GTCombiner(self.mwidth)
 
+        m.submodules.reorder = reorder = ReorderResults(self.mwidth)
+
         # make a series of "eqs" and "gts", splitting a and b into
         # partition chunks
         eqs = Signal(self.mwidth, reset_less=True)
@@ -59,7 +67,7 @@ class PartitionedEqGtGe(Elaboratable):
             end = keys[i]
             eql.append(self.a[start:end] == self.b[start:end])
             gtl.append(self.a[start:end] > self.b[start:end])
-            start = end # for next time round loop
+            start = end  # for next time round loop
         comb += eqs.eq(Cat(*eql))
         comb += gts.eq(Cat(*gtl))
 
@@ -80,11 +88,54 @@ class PartitionedEqGtGe(Elaboratable):
                 comb += aux_input.eq(1)
                 comb += gt_en.eq(1)
 
+        results = Signal(self.mwidth, reset_less=True)
         comb += gtc.gates.eq(self.partition_points.as_sig())
         comb += gtc.eqs.eq(eqs)
         comb += gtc.gts.eq(gts)
         comb += gtc.aux_input.eq(aux_input)
         comb += gtc.gt_en.eq(gt_en)
-        comb += self.output.eq(gtc.outputs)
+        comb += results.eq(gtc.outputs)
+
+        comb += reorder.results_in.eq(results)
+        comb += reorder.gates.eq(self.partition_points.as_sig())
+
+        comb += self.output.eq(reorder.output)
 
         return m
+
+    def ports(self):
+        return [self.a, self.b, self.opcode,
+                self.partition_points.as_sig(),
+                self.output]
+
+
+if __name__ == "__main__":
+    from ieee754.part_mul_add.partpoints import make_partition
+    m = Module()
+    mask = Signal(4)
+    m.submodules.egg = egg = PartitionedEqGtGe(16, make_partition(mask, 16))
+
+    sim = Simulator(m)
+
+    def process():
+        yield mask.eq(0b010)
+        yield egg.a.eq(0xf000)
+        yield egg.b.eq(0)
+        yield egg.opcode.eq(0b00)
+        yield Delay(1e-6)
+        out = yield egg.output
+        print("out", bin(out))
+        yield mask.eq(0b111)
+        yield egg.a.eq(0x0000)
+        yield egg.b.eq(0)
+        yield Delay(1e-6)
+        yield mask.eq(0b010)
+        yield egg.a.eq(0x0000)
+        yield egg.b.eq(0)
+        yield Delay(1e-6)
+        out = yield egg.output
+        print("out", bin(out))
+
+    sim.add_process(process)
+    with sim.write_vcd("eq_gt_ge.vcd", "eq_gt_ge.gtkw", traces=egg.ports()):
+        sim.run()