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