add start of FPADD Fan-in / Fan-out pipeline
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 28 Mar 2019 01:56:14 +0000 (01:56 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 28 Mar 2019 01:56:14 +0000 (01:56 +0000)
src/add/nmigen_add_experiment.py

index a175de31372d1b6cca188f8a9ce79cfebe0b13eb..23f2386cbc7ba92eece293127fff7b323fcf90f7 100644 (file)
@@ -10,6 +10,9 @@ from math import log
 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase, FPNumBase
 from fpbase import MultiShiftRMerge, Trigger
 from singlepipe import (ControlBase, StageChain, UnbufferedPipeline)
+from multipipe import CombMultiOutPipeline
+from multipipe import CombMultiInPipeline, InputPriorityArbiter
+
 #from fpbase import FPNumShiftMultiRight
 
 
@@ -1833,6 +1836,7 @@ class FPADDBase(FPState):
             with m.Else():
                 m.d.sync += self.out_z.stb.eq(1)
 
+
 class FPADDStageIn:
     def __init__(self, width, id_wid):
         self.a = Signal(width)
@@ -1885,6 +1889,106 @@ class FPADDBasePipe(ControlBase):
         return m
 
 
+class PriorityCombPipeline(CombMultiInPipeline):
+    def __init__(self, stage, p_len):
+        p_mux = InputPriorityArbiter(self, p_len)
+        CombMultiInPipeline.__init__(self, stage, p_len=p_len, p_mux=p_mux)
+
+    def ports(self):
+        return self.p_mux.ports()
+
+
+class FPAddInPassThruStage:
+    def __init__(self, width, id_wid):
+        self.width, self.id_wid = width, id_wid
+    def ispec(self): return FPADDStageIn(self.width, self.id_wid)
+    def ospec(self): return self.ospec()
+    def process(self, i): return i
+
+
+class FPADDInMuxPipe(PriorityCombPipeline):
+    def __init__(self, width, id_width, num_rows):
+        self.num_rows = num_rows
+        stage = FPAddInPassThruStage(width, id_width)
+        PriorityCombPipeline.__init__(self, stage, p_len=self.num_rows)
+
+    def ports(self):
+        res = []
+        for i in range(len(self.p)):
+            res += [self.p[i].i_valid, self.p[i].o_ready] + \
+                    self.p[i].i_data.ports()
+        res += [self.n.i_ready, self.n.o_valid] + \
+                self.n.o_data.ports()
+        return res
+
+
+class MuxCombPipeline(CombMultiOutPipeline):
+    def __init__(self, stage, n_len):
+        # HACK: stage is also the n-way multiplexer
+        CombMultiOutPipeline.__init__(self, stage, n_len=n_len, n_mux=stage)
+
+        # HACK: n-mux is also the stage... so set the muxid equal to input mid
+        stage.m_id = self.p.i_data.mid
+
+    def ports(self):
+        return self.p_mux.ports()
+
+
+class FPAddOutPassThruStage:
+    def __init__(self, width, id_wid):
+        self.width, self.id_wid = width, id_wid
+    def ispec(self): return FPADDStageOut(self.width, self.id_wid)
+    def ospec(self): return self.ospec()
+    def process(self, i): return i
+
+
+class FPADDMuxOutPipe(MuxCombPipeline):
+    def __init__(self, width, id_wid, num_rows):
+        self.num_rows = num_rows
+        stage = FPAddOutPassThruStage(width, id_wid)
+        MuxCombPipeline.__init__(self, stage, n_len=self.num_rows)
+
+    def ports(self):
+        res = [self.p.i_valid, self.p.o_ready] + \
+                self.p.i_data.ports()
+        for i in range(len(self.n)):
+            res += [self.n[i].i_ready, self.n[i].o_valid] + \
+                    self.n[i].o_data.ports()
+        return res
+
+
+
+
+class FPADDMuxInOut:
+    """ Reservation-Station version of FPADD pipeline.
+
+        fan-in on
+    """
+    def __init__(self, width, id_wid, num_rows):
+        self.num_rows = num_rows
+        self.inpipe = FPADDInMuxPipe(width, id_wid, num_rows)   # fan-in
+        self.fpadd = FPADDBasePipe(width, id_wid)               # add stage
+        self.outpipe = FPADDMuxOutPipe(width, id_wid, num_rows) # fan-out
+
+        self.p = self.inpipe.p  # kinda annoying,
+        self.n = self.outpipe.n # use pipe in/out as this class in/out
+        self._ports = self.inpipe.ports() + self.outpipe.ports()
+
+    def elaborate(self, platform):
+        m = Module()
+        m.submodules.inpipe = self.inpipe
+        m.submodules.fpadd = self.fpadd
+        m.submodules.outpipe = self.outpipe
+
+        m.d.comb += self.inpipe.n.connect_to_next(self.fpadd.p)
+        m.d.comb += self.fpadd.connect_to_next(self.outpipe)
+
+        return m
+
+    def ports(self):
+        return self._ports
+
+
 class ResArray:
     def __init__(self, width, id_wid):
         self.width = width