create normalise_2 module and use it
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 27 Feb 2019 12:26:16 +0000 (12:26 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Wed, 27 Feb 2019 12:26:16 +0000 (12:26 +0000)
src/add/fpbase.py
src/add/nmigen_add_experiment.py

index c15112a917e116441364d22558bc7305a51a7c4d..e7344fdc1b425ca092480f79fae3f1a3e4588c96 100644 (file)
@@ -96,6 +96,7 @@ class FPNumBase:
         self.is_overflowed = Signal(reset_less=True)
         self.is_denormalised = Signal(reset_less=True)
         self.exp_128 = Signal(reset_less=True)
+        self.exp_lt_n126 = Signal(reset_less=True)
         self.exp_gt_n126 = Signal(reset_less=True)
         self.exp_gt127 = Signal(reset_less=True)
         self.exp_n127 = Signal(reset_less=True)
@@ -112,6 +113,7 @@ class FPNumBase:
         m.d.comb += self.is_denormalised.eq(self._is_denormalised())
         m.d.comb += self.exp_128.eq(self.e == self.P128)
         m.d.comb += self.exp_gt_n126.eq(self.e > self.N126)
+        m.d.comb += self.exp_lt_n126.eq(self.e < self.N126)
         m.d.comb += self.exp_gt127.eq(self.e > self.P127)
         m.d.comb += self.exp_n127.eq(self.e == self.N127)
         m.d.comb += self.exp_n126.eq(self.e == self.N126)
index ac2015153bddb2d3d2a1c3e872a702eab62470fb..513ded1176ad0564fbc1a2043a3ec1b5f13e7442 100644 (file)
@@ -331,10 +331,60 @@ class FPNorm1(FPState):
             m.next = "normalise_2"
 
 
+class FPNorm2Mod:
+
+    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.exp_lt_n126)
+        with m.If(self.out_norm):
+            m.d.comb += [
+                self.out_z.e.eq(self.in_z.e + 1),  # INCREASE exponent
+                self.out_z.m.eq(self.in_z.m >> 1), # shift mantissa DOWN
+                self.out_of.guard.eq(self.in_z.m[0]),
+                self.out_of.m0.eq(self.in_z.m[1]),
+                self.out_of.round_bit.eq(self.in_of.guard),
+                self.out_of.sticky.eq(self.in_of.sticky | self.in_of.round_bit)
+            ]
+
+        return m
+
+
 class FPNorm2(FPState):
 
+    def __init__(self, width):
+        FPState.__init__(self, "normalise_2")
+        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_2(m, self.z, self.of, "round")
+        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 = "round"
 
 
 class FPRoundMod:
@@ -530,9 +580,11 @@ class FPADD:
         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 = self.add_state(FPNorm2(self.width))
         n2.set_inputs({"z": z, "of": of})  # XXX Z as output
         n2.set_outputs({"z": z})  # XXX Z as output
+        n2.mod.setup(m, z, n2.out_z, of, n2.out_of, n2.out_norm)
+        m.submodules.normalise_2 = n2.mod
 
         rn = self.add_state(FPRound(self.width))
         rn.set_inputs({"z": z, "of": of})  # XXX Z as output