hdl.ast: deprecate Value.part, add Value.{bit,word}_select.

Fixes #148.
This commit is contained in:
whitequark 2019-08-03 13:05:41 +00:00
parent bcdc280a87
commit 94e13effad
6 changed files with 105 additions and 29 deletions

View file

@ -146,15 +146,21 @@ class Value(metaclass=ABCMeta):
"""
return ~premise | conclusion
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
@deprecated("instead of `.part`, use `.bit_slip`")
def part(self, offset, width):
"""Indexed part-select.
return Part(self, offset, width, src_loc_at=1)
Selects a constant width but variable offset part of a ``Value``.
def bit_select(self, offset, width):
"""Part-select with bit granularity.
Selects a constant width but variable offset part of a ``Value``, such that successive
parts overlap by all but 1 bit.
Parameters
----------
offset : Value, in
start point of the selected bits
index of first selected bit
width : int
number of selected bits
@ -163,7 +169,27 @@ class Value(metaclass=ABCMeta):
Part, out
Selected part of the ``Value``
"""
return Part(self, offset, width, src_loc_at=1)
return Part(self, offset, width, stride=1, src_loc_at=1)
def word_select(self, offset, width):
"""Part-select with word granularity.
Selects a constant width but variable offset part of a ``Value``, such that successive
parts do not overlap.
Parameters
----------
offset : Value, in
index of first selected word
width : int
number of selected bits
Returns
-------
Part, out
Selected part of the ``Value``
"""
return Part(self, offset, width, stride=width, src_loc_at=1)
def eq(self, value):
"""Assignment.
@ -434,14 +460,17 @@ class Slice(Value):
@final
class Part(Value):
def __init__(self, value, offset, width, *, src_loc_at=0):
def __init__(self, value, offset, width, stride=1, *, src_loc_at=0):
if not isinstance(width, int) or width < 0:
raise TypeError("Part width must be a non-negative integer, not '{!r}'".format(width))
if not isinstance(stride, int) or stride <= 0:
raise TypeError("Part stride must be a positive integer, not '{!r}'".format(stride))
super().__init__(src_loc_at=src_loc_at)
self.value = value
self.offset = Value.wrap(offset)
self.width = width
self.stride = stride
def shape(self):
return self.width, False
@ -453,7 +482,8 @@ class Part(Value):
return self.value._rhs_signals() | self.offset._rhs_signals()
def __repr__(self):
return "(part {} {} {})".format(repr(self.value), repr(self.offset), self.width)
return "(part {} {} {} {})".format(repr(self.value), repr(self.offset),
self.width, self.stride)
@final
@ -1240,7 +1270,7 @@ class ValueKey:
return hash((ValueKey(self.value.value), self.value.start, self.value.end))
elif isinstance(self.value, Part):
return hash((ValueKey(self.value.value), ValueKey(self.value.offset),
self.value.width))
self.value.width, self.value.stride))
elif isinstance(self.value, Cat):
return hash(tuple(ValueKey(o) for o in self.value.parts))
elif isinstance(self.value, ArrayProxy):
@ -1276,7 +1306,8 @@ class ValueKey:
elif isinstance(self.value, Part):
return (ValueKey(self.value.value) == ValueKey(other.value.value) and
ValueKey(self.value.offset) == ValueKey(other.value.offset) and
self.value.width == other.value.width)
self.value.width == other.value.width and
self.value.stride == other.value.stride)
elif isinstance(self.value, Cat):
return all(ValueKey(a) == ValueKey(b)
for a, b in zip(self.value.parts, other.value.parts))

View file

@ -157,7 +157,8 @@ class ValueTransformer(ValueVisitor):
return Slice(self.on_value(value.value), value.start, value.end)
def on_Part(self, value):
return Part(self.on_value(value.value), self.on_value(value.offset), value.width)
return Part(self.on_value(value.value), self.on_value(value.offset),
value.width, value.stride)
def on_Cat(self, value):
return Cat(self.on_value(o) for o in value.parts)