add capability to pass through operands and muxid to output
[ieee754fpu.git] / src / add / nmigen_add_experiment.py
index 121f61b22ab54654bd7147bf8972a524699a362b..0a382f8678a81389775c61b4b547cca8f6399e55 100644 (file)
@@ -2,9 +2,10 @@
 # Copyright (C) Jonathan P Dawson 2013
 # 2013-12-12
 
-from nmigen import Module, Signal, Cat, Mux, Array
+from nmigen import Module, Signal, Cat, Mux, Array, Const
 from nmigen.lib.coding import PriorityEncoder
 from nmigen.cli import main, verilog
+from math import log
 
 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase
 from fpbase import MultiShiftRMerge, Trigger
@@ -26,6 +27,81 @@ class FPState(FPBase):
             setattr(self, k, v)
 
 
+class FPGetSyncOpsMod:
+    def __init__(self, width, num_ops=2):
+        self.width = width
+        self.num_ops = num_ops
+        inops = []
+        outops = []
+        for i in range(num_ops):
+            inops.append(Signal(width, reset_less=True))
+            outops.append(Signal(width, reset_less=True))
+        self.in_op = inops
+        self.out_op = outops
+        self.stb = Signal(num_ops)
+        self.ack = Signal()
+        self.ready = Signal(reset_less=True)
+        self.out_decode = Signal(reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        m.d.comb += self.ready.eq(self.stb == Const(-1, (self.num_ops, False)))
+        m.d.comb += self.out_decode.eq(self.ack & self.ready)
+        with m.If(self.out_decode):
+            for i in range(self.num_ops):
+                m.d.comb += [
+                        self.out_op[i].eq(self.in_op[i]),
+                ]
+        return m
+
+    def ports(self):
+        return self.in_op + self.out_op + [self.stb, self.ack]
+
+
+class InputGroup(Trigger):
+    def __init__(self, width, num_ops=2, num_rows=4):
+        Trigger.__init__(self)
+        self.width = width
+        self.num_ops = num_ops
+        self.num_rows = num_rows
+        self.mmax = int(log(self.num_rows) / log(2))
+        self.rs = []
+        self.mid = Signal(self.mmax, reset_less=True) # multiplex id
+        for i in range(num_rows):
+            self.rs.append(FPGetSyncOpsMod(width, num_ops))
+
+        outops = []
+        for i in range(num_ops):
+            outops.append(Signal(width, reset_less=True))
+        self.out_op = outops
+
+    def elaborate(self, platform):
+        m = Trigger.elaborate(self, platform)
+        pe = PriorityEncoder(self.num_rows)
+        m.submodules.selector = pe
+
+        # connect priority encoder
+        in_ready = []
+        for i in range(self.num_rows):
+            in_ready.append(self.rs[i].ready)
+        m.d.comb += pe.i.eq(Cat(*in_ready))
+        m.d.comb += self.stb.eq(pe.n) # strobe-out valid when encoder is active
+
+        with m.If(pe.n):
+            m.d.sync += self.mid.eq(pe.o)
+            for i in range(self.num_rows):
+                with m.If(pe.o == Const(i, (self.mmax, False))):
+                    for j in range(self.num_ops):
+                        m.d.sync += self.out_op[j].eq(self.rs[i].out_op[j])
+        return m
+
+    def ports(self):
+        res = []
+        for i in range(self.num_rows):
+            inop = self.rs[i]
+            res += inop.in_op + [inop.stb]
+        return self.out_op + res #+ [self.ack + self.stb]
+
 class FPGetOpMod:
     def __init__(self, width):
         self.in_op = FPOp(width)