had to add fixed_width parameter temporarily to confirm that the
[ieee754fpu.git] / src / ieee754 / part / simd_scope.py
index ca1349180896b86abb1b7b7d74c4b7f910d58269..6c21d476f0f050e565e8f86cb753088899f60cf6 100644 (file)
@@ -17,13 +17,8 @@ use as:
 
 """
 
-
-from ieee754.part.util import (DEFAULT_FP_VEC_EL_COUNTS,
-                               DEFAULT_INT_VEC_EL_COUNTS,
-                               FpElWid, IntElWid, SimdMap)
 from nmigen.hdl.ast import Signal
 
-
 class SimdScope:
     """The global scope object for SimdSignal and friends
 
@@ -48,11 +43,13 @@ class SimdScope:
             FpElWid.BF16: 4,
         })
     * elwid: ElWid or nmigen Value with a shape of some ElWid class
-        the current elwid (simd element type)
+        the current elwid (simd element type).  example: Signal(2)
+        or Signal(IntElWid)
     """
 
     __SCOPE_STACK = []
 
+    # XXX REMOVE THIS FUNCTION.  ITS USE IS DANGEROUS.
     @classmethod
     def get(cls):
         """get the current SimdScope. raises a ValueError outside of any
@@ -76,8 +73,7 @@ class SimdScope:
         assert self.__SCOPE_STACK.pop() is self, "inconsistent scope stack"
         return False
 
-    def __init__(self, *, module, elwid=None,
-                 vec_el_counts=None, elwid_type=IntElWid, scalar=False):
+    def __init__(self, module, elwid, vec_el_counts, scalar=False):
 
         # in SIMD mode, must establish module as part of context and inform
         # the module to operate under "SIMD" Type 1 (AST) casting rules,
@@ -87,50 +83,30 @@ class SimdScope:
             from ieee754.part.partsig import SimdSignal
             module._setAstTypeCastFn(SimdSignal.cast)
 
-        if isinstance(elwid, (IntElWid, FpElWid)):
-            elwid_type = type(elwid)
-            if vec_el_counts is None:
-                vec_el_counts = SimdMap({elwid: 1})
-        assert issubclass(elwid_type, (IntElWid, FpElWid))
-        self.elwid_type = elwid_type
-        scalar_elwid = elwid_type(0)
-        if vec_el_counts is None:
-            if scalar:
-                vec_el_counts = SimdMap({scalar_elwid: 1})
-            elif issubclass(elwid_type, FpElWid):
-                vec_el_counts = DEFAULT_FP_VEC_EL_COUNTS
-            else:
-                vec_el_counts = DEFAULT_INT_VEC_EL_COUNTS
-
-        def check(elwid, vec_el_count):
-            assert type(elwid) == elwid_type, "inconsistent ElWid types"
-            vec_el_count = int(vec_el_count)
-            assert vec_el_count != 0 \
-                and (vec_el_count & (vec_el_count - 1)) == 0,\
-                "vec_el_counts values must all be powers of two"
-            return vec_el_count
-
-        self.vec_el_counts = SimdMap.map_with_elwid(check, vec_el_counts)
-        self.full_el_count = max(self.vec_el_counts.values())
-
-        if elwid is not None:
-            self.elwid = elwid
-        elif scalar:
-            self.elwid = scalar_elwid
-        else:
-            self.elwid = Signal(elwid_type)
+        self.elwid = elwid
+        self.vec_el_counts = vec_el_counts
+        self.scalar = scalar
 
     def __repr__(self):
         return (f"SimdScope(\n"
                 f"        elwid={self.elwid},\n"
-                f"        elwid_type={self.elwid_type},\n"
-                f"        vec_el_counts={self.vec_el_counts},\n"
-                f"        full_el_count={self.full_el_count})")
+                f"        vec_el_counts={self.vec_el_counts},\n")
+
+    ##################
+    # from here, the functions are context-aware variants of standard
+    # nmigen API (Signal, Signal.like, Shape) which are to be redirected
+    # to either their standard scalar nmigen equivalents (verbatim)
+    # or to the SimdSignal equivalents.  each one is to be documented
+    # CAREFULLY and CLEARLY.
+    ##################
 
     def Signal(self, shape=None, *, name=None, reset=0, reset_less=False,
-                 attrs=None, decoder=None, src_loc_at=0):
+                 attrs=None, decoder=None, src_loc_at=0,
+                 fixed_width=None): # TODO: *REMOVE* THIS. work out how.
+                                    # BE CAREFUL when using this param
+                                    # it is NOT available in scalar mode
         if self.scalar:
-            # scalar mode, just return a nmigen Signal.
+            # scalar mode, just return a nmigen Signal.  THIS IS IMPORTANT.
             # when passing in SimdShape it should go "oh, this is
             # an isinstance Shape, i will just use its width and sign"
             # which is the entire reason why SimdShape had to derive
@@ -139,13 +115,49 @@ class SimdScope:
                           reset_less=reset_less, attrs=attrs,
                           decoder=decoder, src_loc_at=src_loc_at)
         else:
+            # recursive module import resolution
+            from ieee754.part.partsig import SimdSignal
             # SIMD mode.  shape here can be either a SimdShape,
             # a Shape, or anything else that Signal can take (int or
             # a tuple (int,bool) for (width,sign)
-            s = SimdSignal(mask=self, # should contain *all* context needed
-                          shape=shape, name=name, reset=reset,
+            s = SimdSignal(mask=self, # should contain *all* context needed,
+                                      # which goes all the way through to
+                                      # the layout() function, passing
+                                      # 1) elwid 2) vec_el_counts
+                          shape=shape, # should contain the *secondary*
+                                       # part of the context needed for
+                                       # the layout() function:
+                                       # 3) lane_shapes 4) fixed_width
+                          name=name, reset=reset,
                           reset_less=reset_less, attrs=attrs,
-                          decoder=decoder, src_loc_at=src_loc_at)
+                          decoder=decoder, src_loc_at=src_loc_at,
+                          fixed_width=fixed_width)
             # set the module context so that the SimdSignal can create
             # its own submodules during AST creation
             s.set_module(self.module)
+            return s
+
+    # XXX TODO
+    def Signal_like(self): pass
+        #if self.scalar:
+            # scalar mode, just return nmigen Signal.like.  THIS IS IMPORTANT.
+        # else
+            # simd mode.
+
+    # XXX TODO
+    def Shape(self, width=1, signed=False):
+        if self.scalar:
+            # scalar mode, just return nmigen Shape.  THIS IS IMPORTANT.
+            return Shape(width, signed)
+        else:
+            # SIMD mode. NOTE: for compatibility with Shape, the width
+            # is assumed to be the widths_at_elwid parameter NOT the
+            # fixed width.  this ensures that code that is converted
+            # straight from scalar to SIMD will have the exact same
+            # width at all elwidths, because layout() detects the integer
+            # case and converts it, preserving the width at all elwidths
+            # the names are preserved to ensure parameter-compatibility
+            # with Shape()
+            return SimdShape(self, width=width,   # actually widths_at_elwid
+                                   signed=signed,
+                                   fixed_width=None)