From f6f8213b71bbe50a08d695ed65424b64cb489871 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 2 Jul 2019 09:34:25 +0100 Subject: [PATCH] use new FPBaseData as a "spec" (context), initialised with a dict (pspec) --- src/ieee754/fpadd/add0.py | 20 ++++++------ src/ieee754/fpadd/add1.py | 12 +++---- src/ieee754/fpadd/addstages.py | 14 ++++---- src/ieee754/fpadd/align.py | 26 ++++++++------- src/ieee754/fpadd/pipeline.py | 7 ++-- src/ieee754/fpadd/specialcases.py | 28 +++++++--------- src/ieee754/fpcommon/corrections.py | 11 +++---- src/ieee754/fpcommon/denorm.py | 29 +++++++---------- src/ieee754/fpcommon/getop.py | 46 +++++++++++++++++---------- src/ieee754/fpcommon/normtopack.py | 17 +++++----- src/ieee754/fpcommon/pack.py | 22 ++++++------- src/ieee754/fpcommon/postcalc.py | 15 ++++----- src/ieee754/fpcommon/postnormalise.py | 24 ++++++-------- src/ieee754/fpcommon/roundz.py | 25 ++++++--------- src/ieee754/fpmul/mul0.py | 20 ++++++------ src/ieee754/fpmul/mul1.py | 17 ++++------ src/ieee754/fpmul/mulstages.py | 13 ++++---- src/ieee754/fpmul/pipeline.py | 17 ++++++---- src/ieee754/fpmul/specialcases.py | 26 +++++++-------- src/nmutil/multipipe.py | 3 ++ src/nmutil/nmoperator.py | 2 +- 21 files changed, 192 insertions(+), 202 deletions(-) diff --git a/src/ieee754/fpadd/add0.py b/src/ieee754/fpadd/add0.py index a76374c4..b487b0dd 100644 --- a/src/ieee754/fpadd/add0.py +++ b/src/ieee754/fpadd/add0.py @@ -8,35 +8,37 @@ from nmigen.cli import main, verilog from ieee754.fpcommon.fpbase import FPNumBase, FPNumBaseRecord from ieee754.fpcommon.fpbase import FPState from ieee754.fpcommon.denorm import FPSCData +from ieee754.fpcommon.getop import FPBaseData class FPAddStage0Data: - def __init__(self, width, id_wid): + def __init__(self, width, pspec): self.z = FPNumBaseRecord(width, False) self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) self.tot = Signal(self.z.m_width + 4, reset_less=True) - self.mid = Signal(id_wid, reset_less=True) + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid 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.tot.eq(i.tot), self.mid.eq(i.mid)] + self.tot.eq(i.tot), self.ctx.eq(i.ctx)] class FPAddStage0Mod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid) + return FPSCData(self.width, self.pspec, True) def ospec(self): - return FPAddStage0Data(self.width, self.id_wid) + return FPAddStage0Data(self.width, self.pspec) def process(self, i): return self.o @@ -86,7 +88,7 @@ class FPAddStage0Mod(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) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m @@ -96,7 +98,7 @@ class FPAddStage0(FPState): give greatest accuracy. """ - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "add_0") self.mod = FPAddStage0Mod(width) self.o = self.mod.ospec() diff --git a/src/ieee754/fpadd/add1.py b/src/ieee754/fpadd/add1.py index 408b6075..e434be21 100644 --- a/src/ieee754/fpadd/add1.py +++ b/src/ieee754/fpadd/add1.py @@ -16,17 +16,17 @@ class FPAddStage1Mod(FPState, Elaboratable): detects when tot sum is too big (tot[27] is kinda a carry bit) """ - def __init__(self, width, id_wid): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPAddStage0Data(self.width, self.id_wid) + return FPAddStage0Data(self.width, self.pspec) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid) + return FPAddStage1Data(self.width, self.pspec) def process(self, i): return self.o @@ -65,14 +65,14 @@ class FPAddStage1Mod(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) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m class FPAddStage1(FPState): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "add_1") self.mod = FPAddStage1Mod(width) self.out_z = FPNumBase(width, False) diff --git a/src/ieee754/fpadd/addstages.py b/src/ieee754/fpadd/addstages.py index b398a274..45688c1c 100644 --- a/src/ieee754/fpadd/addstages.py +++ b/src/ieee754/fpadd/addstages.py @@ -18,27 +18,27 @@ from .add1 import FPAddStage1Mod class FPAddAlignSingleAdd(FPState, SimpleHandshake): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "align") self.width = width - self.id_wid = id_wid + self.pspec = pspec SimpleHandshake.__init__(self, self) # pipeline is its own stage self.a1o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid) + return FPSCData(self.width, self.pspec, True) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid) # AddStage1 ospec + return FPAddStage1Data(self.width, self.pspec) # AddStage1 ospec def setup(self, m, i): """ links module to inputs and outputs """ # chain AddAlignSingle, AddStage0 and AddStage1 - mod = FPAddAlignSingleMod(self.width, self.id_wid) - a0mod = FPAddStage0Mod(self.width, self.id_wid) - a1mod = FPAddStage1Mod(self.width, self.id_wid) + mod = FPAddAlignSingleMod(self.width, self.pspec) + a0mod = FPAddStage0Mod(self.width, self.pspec) + a1mod = FPAddStage1Mod(self.width, self.pspec) chain = StageChain([mod, a0mod, a1mod]) chain.setup(m, i) diff --git a/src/ieee754/fpadd/align.py b/src/ieee754/fpadd/align.py index 62dcc379..171365ef 100644 --- a/src/ieee754/fpadd/align.py +++ b/src/ieee754/fpadd/align.py @@ -10,21 +10,23 @@ from ieee754.fpcommon.fpbase import FPNumBaseRecord from ieee754.fpcommon.fpbase import MultiShiftRMerge from ieee754.fpcommon.fpbase import FPState from ieee754.fpcommon.denorm import FPSCData +from ieee754.fpcommon.getop import FPBaseData class FPNumIn2Ops: - def __init__(self, width, id_wid): + def __init__(self, width, pspec): self.a = FPNumBaseRecord(width) self.b = FPNumBaseRecord(width) 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.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid 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.a.eq(i.a), self.b.eq(i.b), self.mid.eq(i.mid)] + self.a.eq(i.a), self.b.eq(i.b), self.ctx.eq(i.ctx)] @@ -72,9 +74,9 @@ class FPAddAlignMultiMod(FPState): class FPAddAlignMulti(FPState): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "align") - self.mod = FPAddAlignMultiMod(width) + self.mod = FPAddAlignMultiMod(width, pspec) self.out_a = FPNumBaseRecord(width) self.out_b = FPNumBaseRecord(width) self.exp_eq = Signal(reset_less=True) @@ -96,17 +98,17 @@ class FPAddAlignMulti(FPState): class FPAddAlignSingleMod(Elaboratable): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid) + return FPSCData(self.width, self.pspec, True) def ospec(self): - return FPNumIn2Ops(self.width, self.id_wid) + return FPNumIn2Ops(self.width, self.pspec) def process(self, i): return self.o @@ -181,7 +183,7 @@ class FPAddAlignSingleMod(Elaboratable): self.o.a.s.eq(self.i.a.s), # whoops forgot sign ] - m.d.comb += self.o.mid.eq(self.i.mid) + m.d.comb += self.o.ctx.eq(self.i.ctx) m.d.comb += self.o.z.eq(self.i.z) m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) m.d.comb += self.o.oz.eq(self.i.oz) @@ -191,9 +193,9 @@ class FPAddAlignSingleMod(Elaboratable): class FPAddAlignSingle(FPState): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "align") - self.mod = FPAddAlignSingleMod(width, id_wid) + self.mod = FPAddAlignSingleMod(width, pspec) self.out_a = FPNumIn(None, width) self.out_b = FPNumIn(None, width) diff --git a/src/ieee754/fpadd/pipeline.py b/src/ieee754/fpadd/pipeline.py index 1458dfef..7dbd254d 100644 --- a/src/ieee754/fpadd/pipeline.py +++ b/src/ieee754/fpadd/pipeline.py @@ -50,11 +50,12 @@ class FPADDMuxInOut(ReservationStations): self.width = width self.id_wid = num_bits(width) self.op_wid = op_wid - self.alu = FPADDBasePipe(width, self.id_wid) + self.pspec = {'id_wid': self.id_wid, 'op_wid': op_wid} + self.alu = FPADDBasePipe(width, self.pspec) ReservationStations.__init__(self, num_rows) def i_specfn(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) + return FPADDBaseData(self.width, self.pspec) def o_specfn(self): - return FPPackData(self.width, self.id_wid, self.op_wid) + return FPPackData(self.width, self.pspec) diff --git a/src/ieee754/fpadd/specialcases.py b/src/ieee754/fpadd/specialcases.py index 2266221a..c0c8e24d 100644 --- a/src/ieee754/fpadd/specialcases.py +++ b/src/ieee754/fpadd/specialcases.py @@ -20,18 +20,17 @@ class FPAddSpecialCasesMod(Elaboratable): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) + return FPADDBaseData(self.width, self.pspec) def ospec(self): - return FPSCData(self.width, self.id_wid, True, self.op_wid) + return FPSCData(self.width, self.pspec, True) def setup(self, m, i): """ links module to inputs and outputs @@ -145,9 +144,7 @@ class FPAddSpecialCasesMod(Elaboratable): m.d.comb += self.o.out_do_z.eq(0) 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) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m @@ -169,7 +166,7 @@ class FPAddSpecialCases(FPState): """ self.mod.setup(m, i, self.out_do_z) m.d.sync += self.out_z.v.eq(self.mod.out_z.v) # only take the output - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) # (and mid) + m.d.sync += self.out_z.ctx.eq(self.mod.o.ctx) # (and mid) def action(self, m): self.idsync(m) @@ -185,25 +182,24 @@ class FPAddSpecialCasesDeNorm(FPState, SimpleHandshake): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): FPState.__init__(self, "special_cases") self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec SimpleHandshake.__init__(self, self) # pipe is its own stage self.out = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) # SC ispec + return FPADDBaseData(self.width, self.pspec) # SC ispec def ospec(self): - return FPSCData(self.width, self.id_wid, True, self.op_wid) # DeNorm + return FPSCData(self.width, self.pspec, True) # DeNorm def setup(self, m, i): """ links module to inputs and outputs """ - smod = FPAddSpecialCasesMod(self.width, self.id_wid) - dmod = FPAddDeNormMod(self.width, self.id_wid) + smod = FPAddSpecialCasesMod(self.width, self.pspec) + dmod = FPAddDeNormMod(self.width, self.pspec, True) chain = StageChain([smod, dmod]) chain.setup(m, i) diff --git a/src/ieee754/fpcommon/corrections.py b/src/ieee754/fpcommon/corrections.py index 09236194..50079226 100644 --- a/src/ieee754/fpcommon/corrections.py +++ b/src/ieee754/fpcommon/corrections.py @@ -10,18 +10,17 @@ from .roundz import FPRoundData class FPCorrectionsMod(Elaboratable): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid # operand width + self.pspec = pspec self.i = self.ispec() self.out_z = self.ospec() def ispec(self): - return FPRoundData(self.width, self.id_wid, self.op_wid) + return FPRoundData(self.width, self.pspec) def ospec(self): - return FPRoundData(self.width, self.id_wid, self.op_wid) + return FPRoundData(self.width, self.pspec) def process(self, i): return self.out_z @@ -62,7 +61,7 @@ class FPCorrections(FPState): self.mod.setup(m, in_z) m.d.sync += self.out_z.eq(self.mod.out_z) - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) + m.d.sync += self.out_z.ctx.eq(self.mod.o.ctx) def action(self, m): m.next = "pack" diff --git a/src/ieee754/fpcommon/denorm.py b/src/ieee754/fpcommon/denorm.py index cea8e2b7..f6b26c2a 100644 --- a/src/ieee754/fpcommon/denorm.py +++ b/src/ieee754/fpcommon/denorm.py @@ -8,11 +8,12 @@ from math import log from ieee754.fpcommon.fpbase import FPNumIn, FPNumOut, FPNumBaseRecord from ieee754.fpcommon.fpbase import FPState, FPNumBase +from ieee754.fpcommon.getop import FPBaseData class FPSCData: - def __init__(self, width, id_wid, m_extra=True, op_wid=None): + def __init__(self, width, pspec, m_extra): # NOTE: difference between z and oz is that oz is created by # special-cases module(s) and will propagate, along with its @@ -23,11 +24,8 @@ class FPSCData: self.z = FPNumBaseRecord(width, False) # denormed result 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 - + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid def __iter__(self): yield from self.a @@ -35,33 +33,28 @@ class FPSCData: yield from self.z yield self.oz yield self.out_do_z - yield self.mid - if op_wid: - yield self.op + yield from self.ctx def eq(self, i): 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)) + self.a.eq(i.a), self.b.eq(i.b), self.ctx.eq(i.ctx)] return ret class FPAddDeNormMod(FPState, Elaboratable): - def __init__(self, width, id_wid, m_extra=True, op_wid=None): + def __init__(self, width, pspec, m_extra): self.width = width - self.id_wid = id_wid + self.pspec = pspec 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, self.op_wid) + return FPSCData(self.width, self.pspec, self.m_extra) def ospec(self): - return FPSCData(self.width, self.id_wid, self.m_extra, self.op_wid) + return FPSCData(self.width, self.pspec, self.m_extra) def process(self, i): return self.o @@ -94,7 +87,7 @@ class FPAddDeNormMod(FPState, Elaboratable): with m.Else(): m.d.comb += self.o.b.m[-1].eq(1) # set top mantissa bit - m.d.comb += self.o.mid.eq(self.i.mid) + m.d.comb += self.o.ctx.eq(self.i.ctx) m.d.comb += self.o.z.eq(self.i.z) m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) m.d.comb += self.o.oz.eq(self.i.oz) diff --git a/src/ieee754/fpcommon/getop.py b/src/ieee754/fpcommon/getop.py index 36352ace..17a8334b 100644 --- a/src/ieee754/fpcommon/getop.py +++ b/src/ieee754/fpcommon/getop.py @@ -84,44 +84,58 @@ class FPNumBase2Ops: class FPBaseData: - def __init__(self, n_ops, width, id_wid, op_wid): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + print (pspec) + self.id_wid = pspec['id_wid'] + self.op_wid = pspec.get('op_wid', 0) + self.mid = Signal(self.id_wid, reset_less=True) # RS multiplex ID + self.op = Signal(self.op_wid, reset_less=True) + + def eq(self, i): + ret = [self.mid.eq(i.mid)] + if self.op_wid: + ret.append(self.op.eq(i.op)) + return ret + + def __iter__(self): + yield self.mid + if self.op_wid: + yield self.op + + def ports(self): + return list(self) + + +class FPADDBaseData: + + def __init__(self, width, pspec, n_ops=2): + self.width = width + self.ctx = FPBaseData(width, pspec) 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.mid = self.ctx.mid # make muxid available here: complicated 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): 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)) + ret.append(self.ctx.eq(i.ctx)) return ret def __iter__(self): if self.ops: yield from self.ops - yield self.mid - if self.id_wid: - yield self.op + yield from self.ctx def ports(self): 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, op_wid=None): diff --git a/src/ieee754/fpcommon/normtopack.py b/src/ieee754/fpcommon/normtopack.py index 49f7c76e..0f05795a 100644 --- a/src/ieee754/fpcommon/normtopack.py +++ b/src/ieee754/fpcommon/normtopack.py @@ -16,28 +16,27 @@ from .pack import FPPackData, FPPackMod class FPNormToPack(FPState, SimpleHandshake): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): FPState.__init__(self, "normalise_1") - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.width = width SimpleHandshake.__init__(self, self) # pipeline is its own stage def ispec(self): - return FPAddStage1Data(self.width, self.id_wid, self.op_wid) + return FPAddStage1Data(self.width, self.pspec) def ospec(self): - return FPPackData(self.width, self.id_wid, self.op_wid) # FPPackMod + return FPPackData(self.width, self.pspec) # FPPackMod def setup(self, m, i): """ links module to inputs and outputs """ # Normalisation, Rounding Corrections, Pack - in a chain - nmod = FPNorm1ModSingle(self.width, self.id_wid) - rmod = FPRoundMod(self.width, self.id_wid) - cmod = FPCorrectionsMod(self.width, self.id_wid) - pmod = FPPackMod(self.width, self.id_wid) + nmod = FPNorm1ModSingle(self.width, self.pspec) + rmod = FPRoundMod(self.width, self.pspec) + cmod = FPCorrectionsMod(self.width, self.pspec) + pmod = FPPackMod(self.width, self.pspec) stages = [nmod, rmod, cmod, pmod] chain = StageChain(stages) chain.setup(m, i) diff --git a/src/ieee754/fpcommon/pack.py b/src/ieee754/fpcommon/pack.py index e03edd4f..5df5ea7c 100644 --- a/src/ieee754/fpcommon/pack.py +++ b/src/ieee754/fpcommon/pack.py @@ -14,27 +14,25 @@ from ieee754.fpcommon.getop import FPBaseData class FPPackData(Object): - def __init__(self, width, id_wid, op_wid): + def __init__(self, width, pspec): 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 - + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid class FPPackMod(Elaboratable): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPRoundData(self.width, self.id_wid, self.op_wid) + return FPRoundData(self.width, self.pspec) def ospec(self): - return FPPackData(self.width, self.id_wid, self.op_wid) + return FPPackData(self.width, self.pspec) def process(self, i): return self.o @@ -50,9 +48,7 @@ class FPPackMod(Elaboratable): z = FPNumBaseRecord(self.width, False) 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) + m.d.comb += self.o.ctx.eq(self.i.ctx) with m.If(~self.i.out_do_z): with m.If(in_z.is_overflowed): m.d.comb += z.inf(self.i.z.s) @@ -83,7 +79,7 @@ class FPPack(FPState): self.mod.setup(m, in_z) m.d.sync += self.out_z.v.eq(self.mod.out_z.v) - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) + m.d.sync += self.out_z.ctx.eq(self.mod.o.ctx) def action(self, m): m.next = "pack_put_z" diff --git a/src/ieee754/fpcommon/postcalc.py b/src/ieee754/fpcommon/postcalc.py index ddb7fb3d..b815f8cf 100644 --- a/src/ieee754/fpcommon/postcalc.py +++ b/src/ieee754/fpcommon/postcalc.py @@ -6,24 +6,23 @@ from nmigen import Signal from ieee754.fpcommon.fpbase import Overflow, FPNumBaseRecord from ieee754.fpcommon.getop import FPBaseData -class FPAddStage1Data(FPBaseData): +class FPAddStage1Data: - def __init__(self, width, id_wid, op_wid=None): - FPBaseData.__init__(self, 0, width, id_wid, op_wid) + def __init__(self, width, pspec): self.z = FPNumBaseRecord(width, False) self.out_do_z = Signal(reset_less=True) self.oz = Signal(width, reset_less=True) self.of = Overflow() + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid def __iter__(self): yield from self.z yield self.out_do_z yield self.oz yield from self.of - yield from FPBaseData.__iter__(self) + yield from self.ctx def eq(self, i): - 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 + 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.ctx.eq(i.ctx)] diff --git a/src/ieee754/fpcommon/postnormalise.py b/src/ieee754/fpcommon/postnormalise.py index c083bc07..0f593865 100644 --- a/src/ieee754/fpcommon/postnormalise.py +++ b/src/ieee754/fpcommon/postnormalise.py @@ -10,43 +10,39 @@ from math import log from ieee754.fpcommon.fpbase import Overflow, FPNumBase, FPNumBaseRecord from ieee754.fpcommon.fpbase import MultiShiftRMerge from ieee754.fpcommon.fpbase import FPState +from ieee754.fpcommon.getop import FPBaseData from .postcalc import FPAddStage1Data class FPNorm1Data: - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): 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 + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid def eq(self, i): 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)) + self.roundz.eq(i.roundz), self.ctx.eq(i.ctx)] return ret class FPNorm1ModSingle(Elaboratable): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPAddStage1Data(self.width, self.id_wid, self.op_wid) + return FPAddStage1Data(self.width, self.pspec) def ospec(self): - return FPNorm1Data(self.width, self.id_wid, self.op_wid) + return FPNorm1Data(self.width, self.pspec) def setup(self, m, i): """ links module to inputs and outputs @@ -135,7 +131,7 @@ class FPNorm1ModSingle(Elaboratable): self.o.z.e.eq(insel_z.e + ediff_n126), ] - m.d.comb += self.o.mid.eq(self.i.mid) + m.d.comb += self.o.ctx.eq(self.i.ctx) m.d.comb += self.o.out_do_z.eq(self.i.out_do_z) m.d.comb += self.o.oz.eq(self.i.oz) diff --git a/src/ieee754/fpcommon/roundz.py b/src/ieee754/fpcommon/roundz.py index dd655510..a0b56868 100644 --- a/src/ieee754/fpcommon/roundz.py +++ b/src/ieee754/fpcommon/roundz.py @@ -7,44 +7,39 @@ from nmigen.cli import main, verilog from ieee754.fpcommon.fpbase import FPNumBase, FPNumBaseRecord from ieee754.fpcommon.fpbase import FPState +from ieee754.fpcommon.getop import FPBaseData from .postnormalise import FPNorm1Data class FPRoundData: - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.z = FPNumBaseRecord(width, False) - self.mid = Signal(id_wid, reset_less=True) # multiplex ID + self.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid # 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): 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)) + self.ctx.eq(i.ctx)] return ret - class FPRoundMod(Elaboratable): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.out_z = self.ospec() def ispec(self): - return FPNorm1Data(self.width, self.id_wid, self.op_wid) + return FPNorm1Data(self.width, self.pspec) def ospec(self): - return FPRoundData(self.width, self.id_wid, self.op_wid) + return FPRoundData(self.width, self.pspec) def process(self, i): return self.out_z @@ -85,7 +80,7 @@ class FPRound(FPState): self.idsync(m) m.d.sync += self.out_z.eq(self.mod.out_z) - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) + m.d.sync += self.out_z.ctx.eq(self.mod.o.ctx) def action(self, m): m.next = "corrections" diff --git a/src/ieee754/fpmul/mul0.py b/src/ieee754/fpmul/mul0.py index ea0753da..59067856 100644 --- a/src/ieee754/fpmul/mul0.py +++ b/src/ieee754/fpmul/mul0.py @@ -13,33 +13,33 @@ from ieee754.fpcommon.getop import FPBaseData class FPMulStage0Data: - def __init__(self, width, id_wid, op_wid=None): - FPBaseData.__init__(self, 0, width, id_wid, op_wid) + def __init__(self, width, pspec): 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.ctx = FPBaseData(width, pspec) + self.mid = self.ctx.mid 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)] + FPBaseData.eq(self, i) + self.product.eq(i.product), self.ctx.eq(i.ctx)] class FPMulStage0Mod(Elaboratable): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid, False, self.op_wid) + return FPSCData(self.width, self.pspec, False) def ospec(self): - return FPMulStage0Data(self.width, self.id_wid, self.op_wid) + return FPMulStage0Data(self.width, self.pspec) def process(self, i): return self.o @@ -72,9 +72,7 @@ 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) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m diff --git a/src/ieee754/fpmul/mul1.py b/src/ieee754/fpmul/mul1.py index 0c5cb6e5..e6e58fc4 100644 --- a/src/ieee754/fpmul/mul1.py +++ b/src/ieee754/fpmul/mul1.py @@ -12,18 +12,17 @@ class FPMulStage1Mod(FPState, Elaboratable): """ Second stage of mul: preparation for normalisation. """ - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPMulStage0Data(self.width, self.id_wid, self.op_wid) + return FPMulStage0Data(self.width, self.pspec) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid, self.op_wid) + return FPAddStage1Data(self.width, self.pspec) def process(self, i): return self.o @@ -51,18 +50,16 @@ 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) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m class FPMulStage1(FPState): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): FPState.__init__(self, "multiply_1") - self.mod = FPMulStage1Mod(width) + self.mod = FPMulStage1Mod(width, pspec) self.out_z = FPNumBaseRecord(width, False) self.out_of = Overflow() self.norm_stb = Signal() diff --git a/src/ieee754/fpmul/mulstages.py b/src/ieee754/fpmul/mulstages.py index 5b6be6ec..53f4cc7f 100644 --- a/src/ieee754/fpmul/mulstages.py +++ b/src/ieee754/fpmul/mulstages.py @@ -14,27 +14,26 @@ from .mul1 import FPMulStage1Mod class FPMulStages(FPState, SimpleHandshake): - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): FPState.__init__(self, "align") self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec SimpleHandshake.__init__(self, self) # pipeline is its own stage self.m1o = self.ospec() def ispec(self): - return FPSCData(self.width, self.id_wid, False, self.op_wid) + return FPSCData(self.width, self.pspec, False) def ospec(self): - return FPAddStage1Data(self.width, self.id_wid, self.op_wid) + return FPAddStage1Data(self.width, self.pspec) def setup(self, m, i): """ links module to inputs and outputs """ # chain MulStage0 and MulStage1 - m0mod = FPMulStage0Mod(self.width, self.id_wid, self.op_wid) - m1mod = FPMulStage1Mod(self.width, self.id_wid, self.op_wid) + m0mod = FPMulStage0Mod(self.width, self.pspec) + m1mod = FPMulStage1Mod(self.width, self.pspec) chain = StageChain([m0mod, m1mod]) chain.setup(m, i) diff --git a/src/ieee754/fpmul/pipeline.py b/src/ieee754/fpmul/pipeline.py index a13ec4ce..d735211c 100644 --- a/src/ieee754/fpmul/pipeline.py +++ b/src/ieee754/fpmul/pipeline.py @@ -18,11 +18,11 @@ from .mulstages import FPMulStages class FPMULBasePipe(ControlBase): - def __init__(self, width, id_wid): + def __init__(self, width, pspec): ControlBase.__init__(self) - self.pipe1 = FPMulSpecialCasesDeNorm(width, id_wid) - self.pipe2 = FPMulStages(width, id_wid) - self.pipe3 = FPNormToPack(width, id_wid) + self.pipe1 = FPMulSpecialCasesDeNorm(width, pspec) + self.pipe2 = FPMulStages(width, pspec) + self.pipe3 = FPNormToPack(width, pspec) self._eqs = self.connect([self.pipe1, self.pipe2, self.pipe3]) @@ -46,13 +46,16 @@ class FPMULMuxInOut(ReservationStations): """ def __init__(self, width, num_rows, op_wid=0): self.width = width + self.pspec = {} self.id_wid = num_bits(width) self.op_wid = op_wid - self.alu = FPMULBasePipe(width, self.id_wid) + self.pspec['id_wid'] = self.id_wid + self.pspec['op_wid'] = self.op_wid + self.alu = FPMULBasePipe(width, self.pspec) ReservationStations.__init__(self, num_rows) def i_specfn(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) + return FPADDBaseData(self.width, self.pspec) def o_specfn(self): - return FPPackData(self.width, self.id_wid, self.op_wid) + return FPPackData(self.width, self.pspec) diff --git a/src/ieee754/fpmul/specialcases.py b/src/ieee754/fpmul/specialcases.py index 18f93dd2..dab89b27 100644 --- a/src/ieee754/fpmul/specialcases.py +++ b/src/ieee754/fpmul/specialcases.py @@ -18,18 +18,17 @@ class FPMulSpecialCasesMod(Elaboratable): https://steve.hollasch.net/cgindex/coding/ieeefloat.html """ - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec self.i = self.ispec() self.o = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) + return FPADDBaseData(self.width, self.pspec) def ospec(self): - return FPSCData(self.width, self.id_wid, False, self.op_wid) + return FPSCData(self.width, self.pspec, False) def setup(self, m, i): """ links module to inputs and outputs @@ -96,7 +95,7 @@ class FPMulSpecialCasesMod(Elaboratable): m.d.comb += self.o.out_do_z.eq(0) m.d.comb += self.o.oz.eq(self.o.z.v) - m.d.comb += self.o.mid.eq(self.i.mid) + m.d.comb += self.o.ctx.eq(self.i.ctx) return m @@ -118,7 +117,7 @@ class FPMulSpecialCases(FPState): """ self.mod.setup(m, i, self.out_do_z) m.d.sync += self.out_z.v.eq(self.mod.out_z.v) # only take the output - m.d.sync += self.out_z.mid.eq(self.mod.o.mid) # (and mid) + m.d.sync += self.out_z.ctx.eq(self.mod.o.ctx) # (and context) def action(self, m): self.idsync(m) @@ -132,25 +131,24 @@ class FPMulSpecialCasesDeNorm(FPState, SimpleHandshake): """ special cases: NaNs, infs, zeros, denormalised """ - def __init__(self, width, id_wid, op_wid=None): + def __init__(self, width, pspec): FPState.__init__(self, "special_cases") self.width = width - self.id_wid = id_wid - self.op_wid = op_wid + self.pspec = pspec SimpleHandshake.__init__(self, self) # pipe is its own stage self.out = self.ospec() def ispec(self): - return FPADDBaseData(self.width, self.id_wid, self.op_wid) + return FPADDBaseData(self.width, self.pspec) def ospec(self): - return FPSCData(self.width, self.id_wid, False, self.op_wid) + return FPSCData(self.width, self.pspec, False) def setup(self, m, i): """ links module to inputs and outputs """ - smod = FPMulSpecialCasesMod(self.width, self.id_wid) - dmod = FPAddDeNormMod(self.width, self.id_wid, False) + smod = FPMulSpecialCasesMod(self.width, self.pspec) + dmod = FPAddDeNormMod(self.width, self.pspec, False) chain = StageChain([smod, dmod]) chain.setup(m, i) diff --git a/src/nmutil/multipipe.py b/src/nmutil/multipipe.py index efc1e005..82e3b8ae 100644 --- a/src/nmutil/multipipe.py +++ b/src/nmutil/multipipe.py @@ -187,6 +187,8 @@ class CombMultiOutPipeline(MultiOutControlBase): # multiplexer id taken from n_mux mid = self.n_mux.m_id + print ("self.n_mux", self.n_mux) + print ("self.n_mux.m_id", self.n_mux.m_id) # temporaries p_valid_i = Signal(reset_less=True) @@ -303,6 +305,7 @@ class CombMuxOutPipe(CombMultiOutPipeline): 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 + print ("combmuxout", self.p.data_i.mid) stage.m_id = self.p.data_i.mid diff --git a/src/nmutil/nmoperator.py b/src/nmutil/nmoperator.py index bdf14572..9a50f650 100644 --- a/src/nmutil/nmoperator.py +++ b/src/nmutil/nmoperator.py @@ -94,8 +94,8 @@ class Visitor2: def arrayproxy_iter2(self, ao, ai): for p in ai.ports(): + print ("arrayproxy - p", p, p.name, ao) op = getattr(ao, p.name) - print ("arrayproxy - p", p, p.name) yield from self.iterator2(op, p) -- 2.30.2