From: Luke Kenneth Casson Leighton Date: Mon, 1 Jul 2019 16:28:23 +0000 (+0100) Subject: add operand down pipeline chain X-Git-Tag: ls180-24jan2020~949 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7d0eedd5131906af7e63ea8f64f8a49b827bb48;p=ieee754fpu.git add operand down pipeline chain --- diff --git a/src/ieee754/fpadd/pipeline.py b/src/ieee754/fpadd/pipeline.py index 7b37a687..1458dfef 100644 --- a/src/ieee754/fpadd/pipeline.py +++ b/src/ieee754/fpadd/pipeline.py @@ -46,14 +46,15 @@ class FPADDMuxInOut(ReservationStations): Fan-in and Fan-out are combinatorial. """ - def __init__(self, width, num_rows): + def __init__(self, width, num_rows, op_wid=None): self.width = width self.id_wid = num_bits(width) + self.op_wid = op_wid self.alu = FPADDBasePipe(width, self.id_wid) ReservationStations.__init__(self, num_rows) def i_specfn(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def o_specfn(self): - return FPPackData(self.width, self.id_wid) + return FPPackData(self.width, self.id_wid, self.op_wid) diff --git a/src/ieee754/fpadd/specialcases.py b/src/ieee754/fpadd/specialcases.py index 4e1a765b..2266221a 100644 --- a/src/ieee754/fpadd/specialcases.py +++ b/src/ieee754/fpadd/specialcases.py @@ -20,17 +20,18 @@ class FPAddSpecialCasesMod(Elaboratable): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPSCData(self.width, self.id_wid) + return FPSCData(self.width, self.id_wid, True, self.op_wid) def setup(self, m, i): """ links module to inputs and outputs @@ -145,6 +146,8 @@ class FPAddSpecialCasesMod(Elaboratable): m.d.comb += self.o.oz.eq(self.o.z.v) m.d.comb += self.o.mid.eq(self.i.mid) + if self.o.op_wid: + m.d.comb += self.o.op.eq(self.i.op) return m @@ -182,18 +185,19 @@ class FPAddSpecialCasesDeNorm(FPState, SimpleHandshake): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): FPState.__init__(self, "special_cases") self.width = width self.id_wid = id_wid + self.op_wid = op_wid SimpleHandshake.__init__(self, self) # pipe is its own stage self.out = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid) # SpecialCases ispec + return FPADDBaseData(self.width, self.id_wid, self.op_wid) # SC ispec def ospec(self): - return FPSCData(self.width, self.id_wid) # DeNorm ospec + return FPSCData(self.width, self.id_wid, True, self.op_wid) # DeNorm def setup(self, m, i): """ links module to inputs and outputs diff --git a/src/ieee754/fpcommon/corrections.py b/src/ieee754/fpcommon/corrections.py index 5869d7e0..09236194 100644 --- a/src/ieee754/fpcommon/corrections.py +++ b/src/ieee754/fpcommon/corrections.py @@ -10,17 +10,18 @@ from .roundz import FPRoundData class FPCorrectionsMod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid # operand width self.i = self.ispec() self.out_z = self.ospec() def ispec(self): - return FPRoundData(self.width, self.id_wid) + return FPRoundData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPRoundData(self.width, self.id_wid) + return FPRoundData(self.width, self.id_wid, self.op_wid) def process(self, i): return self.out_z diff --git a/src/ieee754/fpcommon/denorm.py b/src/ieee754/fpcommon/denorm.py index 559c5ae2..cea8e2b7 100644 --- a/src/ieee754/fpcommon/denorm.py +++ b/src/ieee754/fpcommon/denorm.py @@ -12,7 +12,7 @@ from ieee754.fpcommon.fpbase import FPState, FPNumBase class FPSCData: - def __init__(self, width, id_wid, m_extra=True): + def __init__(self, width, id_wid, m_extra=True, op_wid=None): # NOTE: difference between z and oz is that oz is created by # special-cases module(s) and will propagate, along with its @@ -24,6 +24,10 @@ class FPSCData: self.oz = Signal(width, reset_less=True) # "finished" (bypass) result self.out_do_z = Signal(reset_less=True) # "bypass" enabled self.mid = Signal(id_wid, reset_less=True) # multiplexer ID + self.op_wid = op_wid + if op_wid: + self.op = Signal(op_wid, reset_less=True) # operand + def __iter__(self): yield from self.a @@ -32,26 +36,32 @@ class FPSCData: yield self.oz yield self.out_do_z yield self.mid + if op_wid: + yield self.op def eq(self, i): - return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), + ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), self.a.eq(i.a), self.b.eq(i.b), self.mid.eq(i.mid)] + if self.op_wid: + ret.append(self.op.eq(i.op)) + return ret class FPAddDeNormMod(FPState, Elaboratable): - def __init__(self, width, id_wid, m_extra=True): + def __init__(self, width, id_wid, m_extra=True, op_wid=None): self.width = width self.id_wid = id_wid self.m_extra = m_extra + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid, self.m_extra) + return FPSCData(self.width, self.id_wid, self.m_extra, self.op_wid) def ospec(self): - return FPSCData(self.width, self.id_wid, self.m_extra) + return FPSCData(self.width, self.id_wid, self.m_extra, self.op_wid) def process(self, i): return self.o diff --git a/src/ieee754/fpcommon/getop.py b/src/ieee754/fpcommon/getop.py index 38eb9377..36352ace 100644 --- a/src/ieee754/fpcommon/getop.py +++ b/src/ieee754/fpcommon/getop.py @@ -82,24 +82,49 @@ class FPNumBase2Ops: return [self.a, self.b, self.mid] -class FPADDBaseData: +class FPBaseData: - def __init__(self, width, id_wid): + def __init__(self, n_ops, width, id_wid, op_wid): self.width = width self.id_wid = id_wid - self.a = Signal(width) # operand a - self.b = Signal(width) # operand b + self.op_wid = op_wid + ops = [] + for i in range(n_ops): + name = chr(ord("a")+i) + operand = Signal(width, name=name) + setattr(self, name, operand) + ops.append(operand) + self.ops = ops self.mid = Signal(id_wid, reset_less=True) # RS multiplex ID + self.op = Signal(op_wid, reset_less=True) def eq(self, i): - return [self.a.eq(i.a), self.b.eq(i.b), self.mid.eq(i.mid)] + ret = [] + for op1, op2 in zip(self.ops, i.ops): + ret.append(op1.eq(op2)) + ret.append(self.mid.eq(i.mid)) + if self.op_wid: + ret.append(self.op.eq(i.op)) + return ret + + def __iter__(self): + if self.ops: + yield from self.ops + yield self.mid + if self.id_wid: + yield self.op def ports(self): - return [self.a, self.b, self.mid] + return list(self) + +class FPADDBaseData(FPBaseData): + + def __init__(self, width, id_wid, op_wid): + FPBaseData.__init__(self, 2, width, id_wid, op_wid) class FPGet2OpMod(PrevControl): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): PrevControl.__init__(self) self.width = width self.id_wid = id_wid @@ -108,10 +133,10 @@ class FPGet2OpMod(PrevControl): self.o = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def process(self, i): return self.o @@ -129,10 +154,10 @@ class FPGet2Op(FPState): """ gets operands """ - def __init__(self, in_state, out_state, width, id_wid): + def __init__(self, in_state, out_state, width, id_wid, op_wid=None): FPState.__init__(self, in_state) self.out_state = out_state - self.mod = FPGet2OpMod(width, id_wid) + self.mod = FPGet2OpMod(width, id_wid, op_wid) self.o = self.ospec() self.in_stb = Signal(reset_less=True) self.out_ack = Signal(reset_less=True) diff --git a/src/ieee754/fpcommon/normtopack.py b/src/ieee754/fpcommon/normtopack.py index 9cba7255..49f7c76e 100644 --- a/src/ieee754/fpcommon/normtopack.py +++ b/src/ieee754/fpcommon/normtopack.py @@ -16,17 +16,18 @@ from .pack import FPPackData, FPPackMod class FPNormToPack(FPState, SimpleHandshake): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): FPState.__init__(self, "normalise_1") self.id_wid = id_wid + self.op_wid = op_wid self.width = width SimpleHandshake.__init__(self, self) # pipeline is its own stage def ispec(self): - return FPAddStage1Data(self.width, self.id_wid) # Norm1ModSingle ispec + return FPAddStage1Data(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPPackData(self.width, self.id_wid) # FPPackMod ospec + return FPPackData(self.width, self.id_wid, self.op_wid) # FPPackMod def setup(self, m, i): """ links module to inputs and outputs diff --git a/src/ieee754/fpcommon/pack.py b/src/ieee754/fpcommon/pack.py index 9a9e4d5c..e03edd4f 100644 --- a/src/ieee754/fpcommon/pack.py +++ b/src/ieee754/fpcommon/pack.py @@ -9,29 +9,32 @@ from ieee754.fpcommon.fpbase import FPNumOut, FPNumBaseRecord, FPNumBase from ieee754.fpcommon.fpbase import FPState from .roundz import FPRoundData from nmutil.singlepipe import Object +from ieee754.fpcommon.getop import FPBaseData class FPPackData(Object): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid): Object.__init__(self) self.z = Signal(width, reset_less=True) # result self.mid = Signal(id_wid, reset_less=True) # multiplex ID + self.op = Signal(op_wid or 0, reset_less=True) # operand width class FPPackMod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPRoundData(self.width, self.id_wid) + return FPRoundData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPPackData(self.width, self.id_wid) + return FPPackData(self.width, self.id_wid, self.op_wid) def process(self, i): return self.o @@ -48,6 +51,8 @@ class FPPackMod(Elaboratable): m.submodules.pack_in_z = in_z = FPNumBase(self.i.z) #m.submodules.pack_out_z = out_z = FPNumOut(z) m.d.comb += self.o.mid.eq(self.i.mid) + if self.i.op_wid: + m.d.comb += self.o.op.eq(self.i.op) with m.If(~self.i.out_do_z): with m.If(in_z.is_overflowed): m.d.comb += z.inf(self.i.z.s) diff --git a/src/ieee754/fpcommon/postcalc.py b/src/ieee754/fpcommon/postcalc.py index 61e2f528..ddb7fb3d 100644 --- a/src/ieee754/fpcommon/postcalc.py +++ b/src/ieee754/fpcommon/postcalc.py @@ -4,23 +4,26 @@ from nmigen import Signal from ieee754.fpcommon.fpbase import Overflow, FPNumBaseRecord +from ieee754.fpcommon.getop import FPBaseData -class FPAddStage1Data: +class FPAddStage1Data(FPBaseData): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): + FPBaseData.__init__(self, 0, width, id_wid, op_wid) self.z = FPNumBaseRecord(width, False) self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) self.of = Overflow() - self.mid = Signal(id_wid, reset_less=True) def __iter__(self): yield from self.z yield self.out_do_z yield self.oz yield from self.of - yield self.mid + yield from FPBaseData.__iter__(self) def eq(self, i): - return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), - self.of.eq(i.of), self.mid.eq(i.mid)] + ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), + self.of.eq(i.of),] + FPBaseData.eq(self, i) + + return ret diff --git a/src/ieee754/fpcommon/postnormalise.py b/src/ieee754/fpcommon/postnormalise.py index 1d9ee94f..c083bc07 100644 --- a/src/ieee754/fpcommon/postnormalise.py +++ b/src/ieee754/fpcommon/postnormalise.py @@ -15,31 +15,38 @@ from .postcalc import FPAddStage1Data class FPNorm1Data: - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.roundz = Signal(reset_less=True, name="norm1_roundz") self.z = FPNumBaseRecord(width, False) self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) self.mid = Signal(id_wid, reset_less=True) + self.op_wid = op_wid + if op_wid: + self.op = Signal(op_wid, reset_less=True) # operand def eq(self, i): - return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), + ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), self.roundz.eq(i.roundz), self.mid.eq(i.mid)] + if self.op_wid: + ret.append(self.op.eq(i.op)) + return ret class FPNorm1ModSingle(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPAddStage1Data(self.width, self.id_wid) + return FPAddStage1Data(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPNorm1Data(self.width, self.id_wid) + return FPNorm1Data(self.width, self.id_wid, self.op_wid) def setup(self, m, i): """ links module to inputs and outputs diff --git a/src/ieee754/fpcommon/roundz.py b/src/ieee754/fpcommon/roundz.py index 36253d37..dd655510 100644 --- a/src/ieee754/fpcommon/roundz.py +++ b/src/ieee754/fpcommon/roundz.py @@ -12,31 +12,39 @@ from .postnormalise import FPNorm1Data class FPRoundData: - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.z = FPNumBaseRecord(width, False) self.mid = Signal(id_wid, reset_less=True) # multiplex ID # pipeline bypass [data comes from specialcases] self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) + self.op_wid = op_wid + if op_wid: + self.op = Signal(op_wid, reset_less=True) def eq(self, i): - return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), + ret = [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), self.mid.eq(i.mid)] + if self.op_wid: + ret.append(self.op.eq(i.op)) + return ret + class FPRoundMod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.out_z = self.ospec() def ispec(self): - return FPNorm1Data(self.width, self.id_wid) + return FPNorm1Data(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPRoundData(self.width, self.id_wid) + return FPRoundData(self.width, self.id_wid, self.op_wid) def process(self, i): return self.out_z diff --git a/src/ieee754/fpmul/mul0.py b/src/ieee754/fpmul/mul0.py index 6c264fbc..ea0753da 100644 --- a/src/ieee754/fpmul/mul0.py +++ b/src/ieee754/fpmul/mul0.py @@ -8,36 +8,38 @@ from nmigen.cli import main, verilog from ieee754.fpcommon.fpbase import FPNumBaseRecord from ieee754.fpcommon.fpbase import FPState from ieee754.fpcommon.denorm import FPSCData +from ieee754.fpcommon.getop import FPBaseData class FPMulStage0Data: - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): + FPBaseData.__init__(self, 0, width, id_wid, op_wid) self.z = FPNumBaseRecord(width, False) self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) mw = (self.z.m_width)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1 self.product = Signal(mw, reset_less=True) - self.mid = Signal(id_wid, reset_less=True) def eq(self, i): return [self.z.eq(i.z), self.out_do_z.eq(i.out_do_z), self.oz.eq(i.oz), - self.product.eq(i.product), self.mid.eq(i.mid)] + self.product.eq(i.product)] + FPBaseData.eq(self, i) class FPMulStage0Mod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid, False) + return FPSCData(self.width, self.id_wid, False, self.op_wid) def ospec(self): - return FPMulStage0Data(self.width, self.id_wid) + return FPMulStage0Data(self.width, self.id_wid, self.op_wid) def process(self, i): return self.o @@ -71,6 +73,8 @@ class FPMulStage0Mod(Elaboratable): m.d.comb += self.o.oz.eq(self.i.oz) m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) m.d.comb += self.o.mid.eq(self.i.mid) + if self.o.op_wid: + m.d.comb += self.o.op.eq(self.i.op) return m diff --git a/src/ieee754/fpmul/mul1.py b/src/ieee754/fpmul/mul1.py index d932871b..0c5cb6e5 100644 --- a/src/ieee754/fpmul/mul1.py +++ b/src/ieee754/fpmul/mul1.py @@ -12,17 +12,18 @@ class FPMulStage1Mod(FPState, Elaboratable): """ Second stage of mul: preparation for normalisation. """ - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPMulStage0Data(self.width, self.id_wid) + return FPMulStage0Data(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid) + return FPAddStage1Data(self.width, self.id_wid, self.op_wid) def process(self, i): return self.o @@ -51,6 +52,8 @@ class FPMulStage1Mod(FPState, Elaboratable): m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) m.d.comb += self.o.oz.eq(self.i.oz) m.d.comb += self.o.mid.eq(self.i.mid) + if self.o.op_wid: + m.d.comb += self.o.op.eq(self.i.op) return m diff --git a/src/ieee754/fpmul/mulstages.py b/src/ieee754/fpmul/mulstages.py index e07b05aa..5b6be6ec 100644 --- a/src/ieee754/fpmul/mulstages.py +++ b/src/ieee754/fpmul/mulstages.py @@ -14,26 +14,27 @@ from .mul1 import FPMulStage1Mod class FPMulStages(FPState, SimpleHandshake): - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): FPState.__init__(self, "align") self.width = width self.id_wid = id_wid + self.op_wid = op_wid SimpleHandshake.__init__(self, self) # pipeline is its own stage self.m1o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid, False) + return FPSCData(self.width, self.id_wid, False, self.op_wid) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec + return FPAddStage1Data(self.width, self.id_wid, self.op_wid) def setup(self, m, i): """ links module to inputs and outputs """ # chain MulStage0 and MulStage1 - m0mod = FPMulStage0Mod(self.width, self.id_wid) - m1mod = FPMulStage1Mod(self.width, self.id_wid) + m0mod = FPMulStage0Mod(self.width, self.id_wid, self.op_wid) + m1mod = FPMulStage1Mod(self.width, self.id_wid, self.op_wid) chain = StageChain([m0mod, m1mod]) chain.setup(m, i) diff --git a/src/ieee754/fpmul/pipeline.py b/src/ieee754/fpmul/pipeline.py index 04736600..a13ec4ce 100644 --- a/src/ieee754/fpmul/pipeline.py +++ b/src/ieee754/fpmul/pipeline.py @@ -44,14 +44,15 @@ class FPMULMuxInOut(ReservationStations): Fan-in and Fan-out are combinatorial. """ - def __init__(self, width, num_rows): + def __init__(self, width, num_rows, op_wid=0): self.width = width self.id_wid = num_bits(width) + self.op_wid = op_wid self.alu = FPMULBasePipe(width, self.id_wid) ReservationStations.__init__(self, num_rows) def i_specfn(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def o_specfn(self): - return FPPackData(self.width, self.id_wid) + return FPPackData(self.width, self.id_wid, self.op_wid) diff --git a/src/ieee754/fpmul/specialcases.py b/src/ieee754/fpmul/specialcases.py index 0149bb3b..18f93dd2 100644 --- a/src/ieee754/fpmul/specialcases.py +++ b/src/ieee754/fpmul/specialcases.py @@ -18,17 +18,18 @@ class FPMulSpecialCasesMod(Elaboratable): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): self.width = width self.id_wid = id_wid + self.op_wid = op_wid self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid) + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPSCData(self.width, self.id_wid, False) + return FPSCData(self.width, self.id_wid, False, self.op_wid) def setup(self, m, i): """ links module to inputs and outputs @@ -131,18 +132,19 @@ class FPMulSpecialCasesDeNorm(FPState, SimpleHandshake): """ special cases: NaNs, infs, zeros, denormalised """ - def __init__(self, width, id_wid): + def __init__(self, width, id_wid, op_wid=None): FPState.__init__(self, "special_cases") self.width = width self.id_wid = id_wid + self.op_wid = op_wid SimpleHandshake.__init__(self, self) # pipe is its own stage self.out = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid) # SpecialCases ispec + return FPADDBaseData(self.width, self.id_wid, self.op_wid) def ospec(self): - return FPSCData(self.width, self.id_wid, False) # DeNorm ospec + return FPSCData(self.width, self.id_wid, False, self.op_wid) def setup(self, m, i): """ links module to inputs and outputs