+ # not needed: same as Value.__check_shamt
+ #def __check_shamt(self):
+
+ # TODO: detect if the 2nd operand is a Const, a Signal or a
+ # PartitionedSignal. if it's a Const or a Signal, a global shift
+ # can occur. if it's a PartitionedSignal, that's much more interesting.
+ def ls_op(self, op1, op2, carry, shr_flag=0):
+ op1 = getsig(op1)
+ if isinstance(op2, Const) or isinstance(op2, Signal):
+ scalar = True
+ pa = PartitionedScalarShift(len(op1), self.partpoints)
+ else:
+ scalar = False
+ op2 = getsig(op2)
+ pa = PartitionedDynamicShift(len(op1), self.partpoints)
+ # else:
+ # TODO: case where the *shifter* is a PartitionedSignal but
+ # the thing *being* Shifted is a scalar (Signal, expression)
+ # https://bugs.libre-soc.org/show_bug.cgi?id=718
+ setattr(self.m.submodules, self.get_modname('ls'), pa)
+ comb = self.m.d.comb
+ if scalar:
+ comb += pa.data.eq(op1)
+ comb += pa.shifter.eq(op2)
+ comb += pa.shift_right.eq(shr_flag)
+ else:
+ comb += pa.a.eq(op1)
+ comb += pa.b.eq(op2)
+ comb += pa.shift_right.eq(shr_flag)
+ # XXX TODO: carry-in, carry-out (for arithmetic shift)
+ #comb += pa.carry_in.eq(carry)
+ return (pa.output, 0)
+
+ def __lshift__(self, other):
+ z = Const(0, len(self.partpoints)+1)
+ result, _ = self.ls_op(self, other, carry=z) # TODO, carry
+ return result
+
+ def __rlshift__(self, other):
+ # https://bugs.libre-soc.org/show_bug.cgi?id=718
+ raise NotImplementedError
+ return Operator("<<", [other, self])
+
+ def __rshift__(self, other):
+ z = Const(0, len(self.partpoints)+1)
+ result, _ = self.ls_op(self, other, carry=z, shr_flag=1) # TODO, carry
+ return result
+
+ def __rrshift__(self, other):
+ # https://bugs.libre-soc.org/show_bug.cgi?id=718
+ raise NotImplementedError
+ return Operator(">>", [other, self])
+
+ # binary ops that don't require partitioning
+
+ def __and__(self, other):
+ return applyop(self, other, and_)
+
+ def __rand__(self, other):
+ return applyop(other, self, and_)
+
+ def __or__(self, other):
+ return applyop(self, other, or_)
+
+ def __ror__(self, other):
+ return applyop(other, self, or_)
+
+ def __xor__(self, other):
+ return applyop(self, other, xor)
+
+ def __rxor__(self, other):
+ return applyop(other, self, xor)
+