From 737d2ba74e6d6c8c8e4da4d9ef4c4e2b2c3a640f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Thu, 28 Mar 2019 01:56:14 +0000 Subject: [PATCH] add start of FPADD Fan-in / Fan-out pipeline --- src/add/nmigen_add_experiment.py | 104 +++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/add/nmigen_add_experiment.py b/src/add/nmigen_add_experiment.py index a175de31..23f2386c 100644 --- a/src/add/nmigen_add_experiment.py +++ b/src/add/nmigen_add_experiment.py @@ -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 -- 2.30.2