From e54f2c022828dd2e6a3f2bef011e0555cc5159e4 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Wed, 27 Feb 2019 12:15:34 +0000 Subject: [PATCH] split out first stage normalisation to module and use it --- src/add/fpbase.py | 6 ++++ src/add/nmigen_add_experiment.py | 57 ++++++++++++++++++++++++++++++-- src/add/test_add.py | 2 +- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/add/fpbase.py b/src/add/fpbase.py index 9ee5092b..242f41d8 100644 --- a/src/add/fpbase.py +++ b/src/add/fpbase.py @@ -376,6 +376,12 @@ class Overflow: self.roundz = Signal(reset_less=True) + def copy(self, inp): + return [self.guard.eq(inp.guard), + self.round_bit.eq(inp.round_bit), + self.sticky.eq(inp.sticky), + self.m0.eq(inp.m0)] + def elaborate(self, platform): m = Module() m.d.comb += self.roundz.eq(self.guard & \ diff --git a/src/add/nmigen_add_experiment.py b/src/add/nmigen_add_experiment.py index 7394f2ba..360e2939 100644 --- a/src/add/nmigen_add_experiment.py +++ b/src/add/nmigen_add_experiment.py @@ -274,10 +274,61 @@ class FPAddStage1(FPState): ] +class FPNorm1Mod: + + def __init__(self, width): + self.out_norm = Signal(reset_less=True) + self.in_z = FPNumBase(width, False) + self.out_z = FPNumBase(width, False) + self.in_of = Overflow() + self.out_of = Overflow() + + def setup(self, m, in_z, out_z, in_of, out_of, out_norm): + """ links module to inputs and outputs + """ + m.d.comb += self.in_z.copy(in_z) + m.d.comb += out_z.copy(self.out_z) + m.d.comb += self.in_of.copy(in_of) + m.d.comb += out_of.copy(self.out_of) + m.d.comb += out_norm.eq(self.out_norm) + + def elaborate(self, platform): + m = Module() + m.submodules.norm1_in_overflow = self.in_of + m.submodules.norm1_out_overflow = self.out_of + m.submodules.norm1_in_z = self.in_z + m.submodules.norm1_out_z = self.out_z + m.d.comb += self.out_z.copy(self.in_z) + m.d.comb += self.out_of.copy(self.in_of) + m.d.comb += self.out_norm.eq((self.in_z.m[-1] == 0) & \ + (self.in_z.e > self.in_z.N126)) + with m.If(self.out_norm): + m.d.comb += [ + self.out_z.e.eq(self.in_z.e - 1), # DECREASE exponent + self.out_z.m.eq(self.in_z.m << 1), # shift mantissa UP + self.out_z.m[0].eq(self.in_of.guard), # steal guard (was tot[2]) + self.out_of.guard.eq(self.in_of.round_bit), # round (was tot[1]) + self.out_of.round_bit.eq(0), # reset round bit + self.out_of.m0.eq(self.in_of.guard), + ] + + return m + + class FPNorm1(FPState): + def __init__(self, width): + FPState.__init__(self, "normalise_1") + self.mod = FPNorm1Mod(width) + self.out_norm = Signal(reset_less=True) + self.out_z = FPNumBase(width) + self.out_of = Overflow() + def action(self, m): - self.normalise_1(m, self.z, self.of, "normalise_2") + m.d.sync += self.of.copy(self.out_of) + m.d.sync += self.z.copy(self.out_z) + with m.If(~self.out_norm): + m.next = "normalise_2" class FPNorm2(FPState): @@ -473,9 +524,11 @@ class FPADD: add1.set_inputs({"tot": tot, "z": z}) # Z input passes through add1.set_outputs({"z": z, "of": of}) # XXX Z as output - n1 = self.add_state(FPNorm1("normalise_1")) + n1 = self.add_state(FPNorm1(self.width)) n1.set_inputs({"z": z, "of": of}) # XXX Z as output n1.set_outputs({"z": z}) # XXX Z as output + n1.mod.setup(m, z, n1.out_z, of, n1.out_of, n1.out_norm) + m.submodules.normalise_1 = n1.mod n2 = self.add_state(FPNorm2("normalise_2")) n2.set_inputs({"z": z, "of": of}) # XXX Z as output diff --git a/src/add/test_add.py b/src/add/test_add.py index 39c779db..bd430c61 100644 --- a/src/add/test_add.py +++ b/src/add/test_add.py @@ -67,6 +67,6 @@ def testbench(dut): yield from run_edge_cases(dut, count, add) if __name__ == '__main__': - dut = FPADD(width=32, single_cycle=True) + dut = FPADD(width=32, single_cycle=False) run_simulation(dut, testbench(dut), vcd_name="test_add.vcd") -- 2.30.2