+ offset = Value.cast(offset)
+ if type(offset) is Const and isinstance(width, int):
+ return self[offset.value * width:(offset.value + 1) * width]
+ return Part(self, offset, width, stride=width, src_loc_at=1)
+
+ def matches(self, *patterns):
+ """Pattern matching.
+
+ Matches against a set of patterns, which may be integers or bit strings, recognizing
+ the same grammar as ``Case()``.
+
+ Parameters
+ ----------
+ patterns : int or str
+ Patterns to match against.
+
+ Returns
+ -------
+ Value, out
+ ``1`` if any pattern matches the value, ``0`` otherwise.
+ """
+ matches = []
+ for pattern in patterns:
+ if not isinstance(pattern, (int, str, Enum)):
+ raise SyntaxError("Match pattern must be an integer, a string, or an enumeration, "
+ "not {!r}"
+ .format(pattern))
+ if isinstance(pattern, str) and any(bit not in "01- \t" for bit in pattern):
+ raise SyntaxError("Match pattern '{}' must consist of 0, 1, and - (don't care) "
+ "bits, and may include whitespace"
+ .format(pattern))
+ if (isinstance(pattern, str) and
+ len("".join(pattern.split())) != len(self)):
+ raise SyntaxError("Match pattern '{}' must have the same width as match value "
+ "(which is {})"
+ .format(pattern, len(self)))
+ if isinstance(pattern, int) and bits_for(pattern) > len(self):
+ warnings.warn("Match pattern '{:b}' is wider than match value "
+ "(which has width {}); comparison will never be true"
+ .format(pattern, len(self)),
+ SyntaxWarning, stacklevel=3)
+ continue
+ if isinstance(pattern, str):
+ pattern = "".join(pattern.split()) # remove whitespace
+ mask = int(pattern.replace("0", "1").replace("-", "0"), 2)
+ pattern = int(pattern.replace("-", "0"), 2)
+ matches.append((self & mask) == pattern)
+ elif isinstance(pattern, int):
+ matches.append(self == pattern)
+ elif isinstance(pattern, Enum):
+ matches.append(self == pattern.value)
+ else:
+ assert False
+ if not matches:
+ return Const(0)
+ elif len(matches) == 1:
+ return matches[0]
+ else:
+ return Cat(*matches).any()
+
+ def shift_left(self, amount):
+ """Shift left by constant amount.
+
+ Parameters
+ ----------
+ amount : int
+ Amount to shift by.
+
+ Returns
+ -------
+ Value, out
+ If the amount is positive, the input shifted left. Otherwise, the input shifted right.
+ """
+ if not isinstance(amount, int):
+ raise TypeError("Shift amount must be an integer, not {!r}".format(amount))
+ if amount < 0:
+ return self.shift_right(-amount)
+ if self.shape().signed:
+ return Cat(Const(0, amount), self).as_signed()
+ else:
+ return Cat(Const(0, amount), self) # unsigned
+
+ def shift_right(self, amount):
+ """Shift right by constant amount.
+
+ Parameters
+ ----------
+ amount : int
+ Amount to shift by.
+
+ Returns
+ -------
+ Value, out
+ If the amount is positive, the input shifted right. Otherwise, the input shifted left.
+ """
+ if not isinstance(amount, int):
+ raise TypeError("Shift amount must be an integer, not {!r}".format(amount))
+ if amount < 0:
+ return self.shift_left(-amount)
+ if self.shape().signed:
+ return self[amount:].as_signed()
+ else:
+ return self[amount:] # unsigned
+
+ def rotate_left(self, amount):
+ """Rotate left by constant amount.
+
+ Parameters
+ ----------
+ amount : int
+ Amount to rotate by.
+
+ Returns
+ -------
+ Value, out
+ If the amount is positive, the input rotated left. Otherwise, the input rotated right.
+ """
+ if not isinstance(amount, int):
+ raise TypeError("Rotate amount must be an integer, not {!r}".format(amount))
+ amount %= len(self)
+ return Cat(self[-amount:], self[:-amount]) # meow :3
+
+ def rotate_right(self, amount):
+ """Rotate right by constant amount.
+
+ Parameters
+ ----------
+ amount : int
+ Amount to rotate by.
+
+ Returns
+ -------
+ Value, out
+ If the amount is positive, the input rotated right. Otherwise, the input rotated right.
+ """
+ if not isinstance(amount, int):
+ raise TypeError("Rotate amount must be an integer, not {!r}".format(amount))
+ amount %= len(self)
+ return Cat(self[amount:], self[:amount])