self.out_z = FPNumOut(width, False)
self.out_do_z = Signal(reset_less=True)
+ def setup(self, m, in_a, in_b, out_do_z):
+ """ links module to inputs and outputs
+ """
+ m.submodules.specialcases = self
+ m.d.comb += self.in_a.copy(in_a)
+ m.d.comb += self.in_b.copy(in_b)
+ m.d.comb += out_do_z.eq(self.out_do_z)
+
def elaborate(self, platform):
m = Module()
def setup(self, m, in_a, in_b, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.specialcases = self.mod
- m.d.comb += self.mod.in_a.copy(in_a)
- m.d.comb += self.mod.in_b.copy(in_b)
- #m.d.comb += self.out_z.v.eq(self.mod.out_z.v)
- m.d.comb += self.out_do_z.eq(self.mod.out_do_z)
+ self.mod.setup(m, in_a, in_b, self.out_do_z)
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
m.next = "denormalise"
+class FPAddSpecialCasesDeNorm(FPState, FPID):
+ """ special cases: NaNs, infs, zeros, denormalised
+ NOTE: some of these are unique to add. see "Special Operations"
+ https://steve.hollasch.net/cgindex/coding/ieeefloat.html
+ """
+
+ def __init__(self, width, id_wid):
+ FPState.__init__(self, "special_cases")
+ FPID.__init__(self, id_wid)
+ self.smod = FPAddSpecialCasesMod(width)
+ self.out_z = FPNumOut(width, False)
+ self.out_do_z = Signal(reset_less=True)
+
+ self.dmod = FPAddDeNormMod(width)
+ self.out_a = FPNumBase(width)
+ self.out_b = FPNumBase(width)
+
+ def setup(self, m, in_a, in_b, in_mid):
+ """ links module to inputs and outputs
+ """
+ self.smod.setup(m, in_a, in_b, self.out_do_z)
+ self.dmod.setup(m, in_a, in_b)
+ if self.in_mid is not None:
+ m.d.comb += self.in_mid.eq(in_mid)
+
+ def action(self, m):
+ self.idsync(m)
+ with m.If(self.out_do_z):
+ m.d.sync += self.out_z.v.eq(self.smod.out_z.v) # only take output
+ m.next = "put_z"
+ with m.Else():
+ m.next = "align"
+ m.d.sync += self.out_a.copy(self.dmod.out_a)
+ m.d.sync += self.out_b.copy(self.dmod.out_b)
+
+
class FPAddDeNormMod(FPState):
def __init__(self, width):
self.out_a = FPNumBase(width)
self.out_b = FPNumBase(width)
+ def setup(self, m, in_a, in_b):
+ """ links module to inputs and outputs
+ """
+ m.submodules.denormalise = self
+ m.d.comb += self.in_a.copy(in_a)
+ m.d.comb += self.in_b.copy(in_b)
+
def elaborate(self, platform):
m = Module()
m.submodules.denorm_in_a = self.in_a
def setup(self, m, in_a, in_b, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.denormalise = self.mod
- m.d.comb += self.mod.in_a.copy(in_a)
- m.d.comb += self.mod.in_b.copy(in_b)
+ self.mod.setup(m, in_a, in_b)
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
self.out_a = FPNumIn(None, width)
self.out_b = FPNumIn(None, width)
+ def setup(self, m, in_a, in_b):
+ """ links module to inputs and outputs
+ """
+ m.submodules.align = self
+ m.d.comb += self.in_a.copy(in_a)
+ m.d.comb += self.in_b.copy(in_b)
+
def elaborate(self, platform):
""" Aligns A against B or B against A, depending on which has the
greater exponent. This is done in a *single* cycle using
def setup(self, m, in_a, in_b, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.align = self.mod
- m.d.comb += self.mod.in_a.copy(in_a)
- m.d.comb += self.mod.in_b.copy(in_b)
+ self.mod.setup(m, in_a, in_b)
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
m.next = "add_0"
+class FPAddAlignSingleAdd(FPState, FPID):
+
+ def __init__(self, width, id_wid):
+ FPState.__init__(self, "align")
+ FPID.__init__(self, id_wid)
+ self.mod = FPAddAlignSingleMod(width)
+ self.out_a = FPNumIn(None, width)
+ self.out_b = FPNumIn(None, width)
+
+ self.a0mod = FPAddStage0Mod(width)
+ self.a0_out_z = FPNumBase(width, False)
+ self.out_tot = Signal(self.a0_out_z.m_width + 4, reset_less=True)
+ self.a0_out_z = FPNumBase(width, False)
+
+ self.a1mod = FPAddStage1Mod(width)
+ self.out_z = FPNumBase(width, False)
+ self.out_of = Overflow()
+
+ def setup(self, m, in_a, in_b, in_mid):
+ """ links module to inputs and outputs
+ """
+ self.mod.setup(m, in_a, in_b)
+ m.d.comb += self.out_a.copy(self.mod.out_a)
+ m.d.comb += self.out_b.copy(self.mod.out_b)
+
+ self.a0mod.setup(m, self.out_a, self.out_b)
+ m.d.comb += self.a0_out_z.copy(self.a0mod.out_z)
+ m.d.comb += self.out_tot.eq(self.a0mod.out_tot)
+
+ self.a1mod.setup(m, self.out_tot, self.a0_out_z)
+
+ if self.in_mid is not None:
+ m.d.comb += self.in_mid.eq(in_mid)
+
+ def action(self, m):
+ self.idsync(m)
+ m.d.sync += self.out_of.copy(self.a1mod.out_of)
+ m.d.sync += self.out_z.copy(self.a1mod.out_z)
+ m.next = "normalise_1"
+
+
class FPAddStage0Mod:
def __init__(self, width):
self.out_z = FPNumBase(width, False)
self.out_tot = Signal(self.out_z.m_width + 4, reset_less=True)
+ def setup(self, m, in_a, in_b):
+ """ links module to inputs and outputs
+ """
+ m.submodules.add0 = self
+ m.d.comb += self.in_a.copy(in_a)
+ m.d.comb += self.in_b.copy(in_b)
+
def elaborate(self, platform):
m = Module()
m.submodules.add0_in_a = self.in_a
def setup(self, m, in_a, in_b, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.add0 = self.mod
- m.d.comb += self.mod.in_a.copy(in_a)
- m.d.comb += self.mod.in_b.copy(in_b)
+ self.mod.setup(m, in_a, in_b)
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
self.out_z = FPNumBase(width, False)
self.out_of = Overflow()
+ def setup(self, m, in_tot, in_z):
+ """ links module to inputs and outputs
+ """
+ m.submodules.add1 = self
+ m.submodules.add1_out_overflow = self.out_of
+
+ m.d.comb += self.in_z.copy(in_z)
+ m.d.comb += self.in_tot.eq(in_tot)
+
def elaborate(self, platform):
m = Module()
#m.submodules.norm1_in_overflow = self.in_of
def setup(self, m, in_tot, in_z, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.add1 = self.mod
- m.submodules.add1_out_overflow = self.out_of
-
- m.d.comb += self.mod.in_z.copy(in_z)
- m.d.comb += self.mod.in_tot.eq(in_tot)
+ self.mod.setup(m, in_tot, in_z)
m.d.sync += self.norm_stb.eq(0) # sets to zero when not in add1 state
def __init__(self, width, id_wid):
FPID.__init__(self, id_wid)
FPState.__init__(self, "normalise_1")
- self.mod = FPNorm1ModSingle(width)
- self.n_out_z = FPNumBase(width)
- self.n_out_roundz = Signal(reset_less=True)
-
- self.rmod = FPRoundMod(width)
- self.r_out_z = FPNumBase(width)
-
- self.cmod = FPCorrectionsMod(width)
- self.out_z = FPNumBase(width)
+ self.width = width
def setup(self, m, in_z, in_of, in_mid):
""" links module to inputs and outputs
"""
- self.mod.setup(m, in_z, in_of, self.n_out_z)
- self.rmod.setup(m, self.n_out_z, self.n_out_roundz)
- m.d.comb += self.n_out_roundz.eq(self.mod.out_of.roundz)
- m.d.comb += self.r_out_z.copy(self.rmod.out_z)
- self.cmod.setup(m, self.r_out_z)
+ # Normalisation (chained to input in_z+in_of)
+ nmod = FPNorm1ModSingle(self.width)
+ n_out_z = FPNumBase(self.width)
+ n_out_roundz = Signal(reset_less=True)
+ nmod.setup(m, in_z, in_of, n_out_z)
+
+ # Rounding (chained to normalisation)
+ rmod = FPRoundMod(self.width)
+ r_out_z = FPNumBase(self.width)
+ rmod.setup(m, n_out_z, n_out_roundz)
+ m.d.comb += n_out_roundz.eq(nmod.out_of.roundz)
+ m.d.comb += r_out_z.copy(rmod.out_z)
+
+ # Corrections (chained to rounding)
+ cmod = FPCorrectionsMod(self.width)
+ c_out_z = FPNumBase(self.width)
+ cmod.setup(m, r_out_z)
+ m.d.comb += c_out_z.copy(cmod.out_z)
+
+ # Pack (chained to corrections)
+ self.pmod = FPPackMod(self.width)
+ self.out_z = FPNumBase(self.width)
+ self.pmod.setup(m, c_out_z)
+
+ # Multiplex ID
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
def action(self, m):
- self.idsync(m)
- m.next = "pack"
- m.d.sync += self.out_z.copy(self.cmod.out_z)
+ self.idsync(m) # copies incoming ID to outgoing
+ m.d.sync += self.out_z.v.eq(self.pmod.out_z.v) # outputs packed result
+ m.next = "pack_put_z"
class FPRoundMod:
self.in_z = FPNumOut(width, False)
self.out_z = FPNumOut(width, False)
+ def setup(self, m, in_z):
+ """ links module to inputs and outputs
+ """
+ m.submodules.pack = self
+ m.d.comb += self.in_z.copy(in_z)
+
def elaborate(self, platform):
m = Module()
m.submodules.pack_in_z = self.in_z
def setup(self, m, in_z, in_mid):
""" links module to inputs and outputs
"""
- m.submodules.pack = self.mod
- m.d.comb += self.mod.in_z.copy(in_z)
+ self.mod.setup(m, in_z)
if self.in_mid is not None:
m.d.comb += self.in_mid.eq(in_mid)
a = get.out_op1
b = get.out_op2
- sc = self.add_state(FPAddSpecialCases(self.width, self.id_wid))
+ sc = self.add_state(FPAddSpecialCasesDeNorm(self.width, self.id_wid))
sc.setup(m, a, b, self.in_mid)
- dn = self.add_state(FPAddDeNorm(self.width, self.id_wid))
- dn.setup(m, a, b, sc.in_mid)
-
- if self.single_cycle:
- alm = self.add_state(FPAddAlignSingle(self.width, self.id_wid))
- alm.setup(m, dn.out_a, dn.out_b, dn.in_mid)
- else:
- alm = self.add_state(FPAddAlignMulti(self.width, self.id_wid))
- alm.setup(m, dn.out_a, dn.out_b, dn.in_mid)
-
- add0 = self.add_state(FPAddStage0(self.width, self.id_wid))
- add0.setup(m, alm.out_a, alm.out_b, alm.in_mid)
-
- add1 = self.add_state(FPAddStage1(self.width, self.id_wid))
- add1.setup(m, add0.out_tot, add0.out_z, add0.in_mid)
+ alm = self.add_state(FPAddAlignSingleAdd(self.width, self.id_wid))
+ alm.setup(m, sc.out_a, sc.out_b, sc.in_mid)
n1 = self.add_state(FPNormToPack(self.width, self.id_wid))
- n1.setup(m, add1.out_z, add1.out_of, add0.in_mid)
+ n1.setup(m, alm.out_z, alm.out_of, alm.in_mid)
- pa = self.add_state(FPPack(self.width, self.id_wid))
- pa.setup(m, n1.out_z, n1.in_mid)
-
- ppz = self.add_state(FPPutZ("pack_put_z", pa.out_z, self.out_z,
- pa.in_mid, self.out_mid))
+ ppz = self.add_state(FPPutZ("pack_put_z", n1.out_z, self.out_z,
+ n1.in_mid, self.out_mid))
pz = self.add_state(FPPutZ("put_z", sc.out_z, self.out_z,
- pa.in_mid, self.out_mid))
+ sc.in_mid, self.out_mid))
class FPADDBase(FPState, FPID):
* id_wid: an identifier that is sync-connected to the input
* single_cycle: True indicates each stage to complete in 1 clock
"""
- FPID.__init__(self, id_wid)
self.width = width
self.id_wid = id_wid
self.single_cycle = single_cycle
+ self.ids = FPID(id_wid)
self.in_a = FPOp(width)
self.in_b = FPOp(width)
self.out_z = FPOp(width)
ab = FPADDBase(self.width, self.id_wid, self.single_cycle)
ab = self.add_state(ab)
- ab.setup(m, a, b, getb.out_decode, self.in_mid,
- self.out_z, self.out_mid)
+ ab.setup(m, a, b, getb.out_decode, self.ids.in_mid,
+ self.out_z, self.ids.out_mid)
#pz = self.add_state(FPPutZ("put_z", ab.out_z, self.out_z,
# ab.out_mid, self.out_mid))