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)
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
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
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
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
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
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
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
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
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
""" 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)
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
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
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)
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
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
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
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
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
""" 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
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
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)
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)
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
""" 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