[Libre-soc-bugs] [Bug 716] PartitionedSignal Slice and Part needed for __getitem__
bugzilla-daemon at libre-soc.org
bugzilla-daemon at libre-soc.org
Sun Oct 24 20:24:55 BST 2021
https://bugs.libre-soc.org/show_bug.cgi?id=716
--- Comment #19 from Jacob Lifshay <programmerjake at gmail.com> ---
(In reply to Luke Kenneth Casson Leighton from comment #18)
> (In reply to Luke Kenneth Casson Leighton from comment #17)
>
> > the answer is: an adapter submodule.
> >
> > the exact details of how that works will emerge from
> > the examples, TBD. i will write a couple now.
>
> oo. err and um. that's interesting. an add of a 3 bit
> sliced quantity with a 2 bit (element width=2bit) quantity
> requires sign (or zero) extension prior to partition
> expansion.
>
> this is going to be interesting (translation: hairy)
The answer to all of those conversions is to have a SimdSignal.cast method that
handles conversion of an input nmigen Value or SimdSignal to the desired
SimdShape:
Full conversion implementation:
class SimdSignal(...):
@staticmethod
def cast(value, *, shape=None, scope):
# scope injected by calling this method as
# scope.Signal_cast(value, shape=shape), which is a
# partial() of SimdSignal.cast
if shape is not None:
assert shape.scope is scope
if isinstance(value, SimdSignal):
assert value.shape().scope is scope
if shape is None or shape == value.shape():
return value
# I'm assuming SwizzleKey is already replaced by SimdScope.
# from_value handles splatting a scalar nmigen Value if needed.
src = SwizzledSimdValue.from_value(scope, value)
swizzles = {}
for src_el, dst_el in zip(src.shape().elements(),
shape.elements()):
elwid = src_el.elwid
# SimdShape always iterates elements in the same order across all
# SimdShapes for a particular scope.
assert elwid == dst_el.elwid
if elwid not in swizzles:
swizzles[elwid] = Swizzle.from_const(0, shape.width)
# get bits for current src_el
el = src.swizzles[elwid][src_el.slice]
if src_el.shape.signed: # *src* determines sign/zero extension
# truncate/sign-extend
el = el.convert_s_to(dst_el.shape)
else:
# truncate/zero-extend
el = el.convert_u_to(dst_el.shape)
# assign converted bits to dest
swizzles[elwid].bits[dst_rl.slice] = el.bits
# oops, I forgot shape argument for __init__
return SwizzledSimdValue(scope, swizzles, shape=shape)
now, all ops can use:
ops_input_arg = SimdSignal.cast(ops_input_arg, shape=desired_shape,
scope=scope)
e.g.:
def __add__(self, other):
l_shape = self.shape()
scope = l_shape.scope
# splat scalars to SimdSignal
other = SimdSignal.cast(other, scope=scope)
r_shape = other.shape()
def get_el_shape(l, r):
# let nmigen compute result element's shape
return (Const(0, l) + Const(0, r)).shape()
el_shapes = SimdMap.map(get_el_shape, l_shape.el_shapes,
r_shape.el_shapes)
shape = SimdShape(el_shapes, scope=scope)
# could have a SimdShape.map method letting us write:
# shape = SimdShape.map(get_el_shape, l_shape, r_shape)
# convert to result's shape
lhs = SimdSignal.cast(self, shape=shape, scope=scope)
rhs = SimdSignal.cast(other, shape=shape, scope=scope)
# do add
return lhs.add_op(lhs, rhs, carry=0)
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the libre-soc-bugs
mailing list