From: whitequark Date: Fri, 11 Oct 2019 11:37:26 +0000 (+0000) Subject: hdl.ast: Operator.{op→operator} X-Git-Tag: v0.1rc1~25 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fa1e466a654543ba6803690a18f53ac38683bc65;p=nmigen.git hdl.ast: Operator.{op→operator} Both "operator" and "operand" were shortened to "op" in different places in code, which caused confusion. --- diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index 472cc57..0949d5e 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -123,64 +123,64 @@ class _RHSValueCompiler(_ValueCompiler): shape = value.shape() if len(value.operands) == 1: arg, = map(self, value.operands) - if value.op == "~": + if value.operator == "~": return lambda state: normalize(~arg(state), shape) - if value.op == "-": + if value.operator == "-": return lambda state: normalize(-arg(state), shape) - if value.op == "b": + if value.operator == "b": return lambda state: normalize(bool(arg(state)), shape) - if value.op == "r|": + if value.operator == "r|": return lambda state: normalize(arg(state) != 0, shape) - if value.op == "r&": + if value.operator == "r&": val, = value.operands mask = (1 << len(val)) - 1 return lambda state: normalize(arg(state) == mask, shape) - if value.op == "r^": + if value.operator == "r^": # Believe it or not, this is the fastest way to compute a sideways XOR in Python. return lambda state: normalize(format(arg(state), "b").count("1") % 2, shape) elif len(value.operands) == 2: lhs, rhs = map(self, value.operands) - if value.op == "+": + if value.operator == "+": return lambda state: normalize(lhs(state) + rhs(state), shape) - if value.op == "-": + if value.operator == "-": return lambda state: normalize(lhs(state) - rhs(state), shape) - if value.op == "*": + if value.operator == "*": return lambda state: normalize(lhs(state) * rhs(state), shape) - if value.op == "//": + if value.operator == "//": def floordiv(lhs, rhs): return 0 if rhs == 0 else lhs // rhs return lambda state: normalize(floordiv(lhs(state), rhs(state)), shape) - if value.op == "&": + if value.operator == "&": return lambda state: normalize(lhs(state) & rhs(state), shape) - if value.op == "|": + if value.operator == "|": return lambda state: normalize(lhs(state) | rhs(state), shape) - if value.op == "^": + if value.operator == "^": return lambda state: normalize(lhs(state) ^ rhs(state), shape) - if value.op == "<<": + if value.operator == "<<": def sshl(lhs, rhs): return lhs << rhs if rhs >= 0 else lhs >> -rhs return lambda state: normalize(sshl(lhs(state), rhs(state)), shape) - if value.op == ">>": + if value.operator == ">>": def sshr(lhs, rhs): return lhs >> rhs if rhs >= 0 else lhs << -rhs return lambda state: normalize(sshr(lhs(state), rhs(state)), shape) - if value.op == "==": + if value.operator == "==": return lambda state: normalize(lhs(state) == rhs(state), shape) - if value.op == "!=": + if value.operator == "!=": return lambda state: normalize(lhs(state) != rhs(state), shape) - if value.op == "<": + if value.operator == "<": return lambda state: normalize(lhs(state) < rhs(state), shape) - if value.op == "<=": + if value.operator == "<=": return lambda state: normalize(lhs(state) <= rhs(state), shape) - if value.op == ">": + if value.operator == ">": return lambda state: normalize(lhs(state) > rhs(state), shape) - if value.op == ">=": + if value.operator == ">=": return lambda state: normalize(lhs(state) >= rhs(state), shape) elif len(value.operands) == 3: - if value.op == "m": + if value.operator == "m": sel, val1, val0 = map(self, value.operands) return lambda state: val1(state) if sel(state) else val0(state) - raise NotImplementedError("Operator '{}' not implemented".format(value.op)) # :nocov: + raise NotImplementedError("Operator '{}' not implemented".format(value.operator)) # :nocov: def on_Slice(self, value): shape = value.shape() diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 7dbe085..43a1bd0 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -452,7 +452,7 @@ class _RHSValueCompiler(_ValueCompiler): arg_bits, arg_sign = arg.shape() res_bits, res_sign = value.shape() res = self.s.rtlil.wire(width=res_bits, src=src(value.src_loc)) - self.s.rtlil.cell(self.operator_map[(1, value.op)], ports={ + self.s.rtlil.cell(self.operator_map[(1, value.operator)], ports={ "\\A": self(arg), "\\Y": res, }, params={ @@ -485,7 +485,7 @@ class _RHSValueCompiler(_ValueCompiler): lhs, rhs = value.operands lhs_bits, lhs_sign = lhs.shape() rhs_bits, rhs_sign = rhs.shape() - if lhs_sign == rhs_sign or value.op in ("<<", ">>", "**"): + if lhs_sign == rhs_sign or value.operator in ("<<", ">>", "**"): lhs_wire = self(lhs) rhs_wire = self(rhs) else: @@ -494,7 +494,7 @@ class _RHSValueCompiler(_ValueCompiler): rhs_wire = self.match_shape(rhs, rhs_bits, rhs_sign) res_bits, res_sign = value.shape() res = self.s.rtlil.wire(width=res_bits, src=src(value.src_loc)) - self.s.rtlil.cell(self.operator_map[(2, value.op)], ports={ + self.s.rtlil.cell(self.operator_map[(2, value.operator)], ports={ "\\A": lhs_wire, "\\B": rhs_wire, "\\Y": res, @@ -505,7 +505,7 @@ class _RHSValueCompiler(_ValueCompiler): "B_WIDTH": rhs_bits, "Y_WIDTH": res_bits, }, src=src(value.src_loc)) - if value.op in ("//", "%"): + if value.operator in ("//", "%"): # RTLIL leaves division by zero undefined, but we require it to return zero. divmod_res = res res = self.s.rtlil.wire(width=res_bits, src=src(value.src_loc)) @@ -544,7 +544,7 @@ class _RHSValueCompiler(_ValueCompiler): elif len(value.operands) == 2: return self.on_Operator_binary(value) elif len(value.operands) == 3: - assert value.op == "m" + assert value.operator == "m" return self.on_Operator_mux(value) else: raise TypeError # :nocov: diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index db1a70b..f142c1d 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -453,79 +453,84 @@ class AnySeq(AnyValue): @final class Operator(Value): - def __init__(self, op, operands, *, src_loc_at=0): + def __init__(self, operator, operands, *, src_loc_at=0): super().__init__(src_loc_at=1 + src_loc_at) - self.op = op - self.operands = [Value.cast(o) for o in operands] + self.operator = operator + self.operands = [Value.cast(op) for op in operands] - @staticmethod - def _bitwise_binary_shape(a_shape, b_shape): - a_bits, a_sign = a_shape - b_bits, b_sign = b_shape - if not a_sign and not b_sign: - # both operands unsigned - return max(a_bits, b_bits), False - elif a_sign and b_sign: - # both operands signed - return max(a_bits, b_bits), True - elif not a_sign and b_sign: - # first operand unsigned (add sign bit), second operand signed - return max(a_bits + 1, b_bits), True - else: - # first signed, second operand unsigned (add sign bit) - return max(a_bits, b_bits + 1), True + # TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension + @property + @deprecated("instead of `.op`, use `.operator`") + def op(self): + return self.operator def shape(self): + def _bitwise_binary_shape(a_shape, b_shape): + a_bits, a_sign = a_shape + b_bits, b_sign = b_shape + if not a_sign and not b_sign: + # both operands unsigned + return max(a_bits, b_bits), False + elif a_sign and b_sign: + # both operands signed + return max(a_bits, b_bits), True + elif not a_sign and b_sign: + # first operand unsigned (add sign bit), second operand signed + return max(a_bits + 1, b_bits), True + else: + # first signed, second operand unsigned (add sign bit) + return max(a_bits, b_bits + 1), True + op_shapes = list(map(lambda x: x.shape(), self.operands)) if len(op_shapes) == 1: (a_width, a_signed), = op_shapes - if self.op in ("+", "~"): + if self.operator in ("+", "~"): return a_width, a_signed - if self.op == "-": + if self.operator == "-": if not a_signed: return a_width + 1, True else: return a_width, a_signed - if self.op in ("b", "r|", "r&", "r^"): + if self.operator in ("b", "r|", "r&", "r^"): return 1, False elif len(op_shapes) == 2: (a_width, a_signed), (b_width, b_signed) = op_shapes - if self.op == "+" or self.op == "-": - width, signed = self._bitwise_binary_shape(*op_shapes) + if self.operator == "+" or self.operator == "-": + width, signed = _bitwise_binary_shape(*op_shapes) return width + 1, signed - if self.op == "*": + if self.operator == "*": return a_width + b_width, a_signed or b_signed - if self.op in ("//", "%"): + if self.operator in ("//", "%"): assert not b_signed return a_width, a_signed - if self.op in ("<", "<=", "==", "!=", ">", ">="): + if self.operator in ("<", "<=", "==", "!=", ">", ">="): return 1, False - if self.op in ("&", "^", "|"): - return self._bitwise_binary_shape(*op_shapes) - if self.op == "<<": + if self.operator in ("&", "^", "|"): + return _bitwise_binary_shape(*op_shapes) + if self.operator == "<<": if b_signed: extra = 2 ** (b_width - 1) - 1 else: extra = 2 ** (b_width) - 1 return a_width + extra, a_signed - if self.op == ">>": + if self.operator == ">>": if b_signed: extra = 2 ** (b_width - 1) else: extra = 0 return a_width + extra, a_signed elif len(op_shapes) == 3: - if self.op == "m": + if self.operator == "m": s_shape, a_shape, b_shape = op_shapes - return self._bitwise_binary_shape(a_shape, b_shape) + return _bitwise_binary_shape(a_shape, b_shape) raise NotImplementedError("Operator {}/{} not implemented" - .format(self.op, len(op_shapes))) # :nocov: + .format(self.operator, len(op_shapes))) # :nocov: def _rhs_signals(self): return union(op._rhs_signals() for op in self.operands) def __repr__(self): - return "({} {})".format(self.op, " ".join(map(repr, self.operands))) + return "({} {})".format(self.operator, " ".join(map(repr, self.operands))) def Mux(sel, val1, val0): @@ -1478,7 +1483,8 @@ class ValueKey: elif isinstance(self.value, (ClockSignal, ResetSignal)): self._hash = hash(self.value.domain) elif isinstance(self.value, Operator): - self._hash = hash((self.value.op, tuple(ValueKey(o) for o in self.value.operands))) + self._hash = hash((self.value.operator, + tuple(ValueKey(o) for o in self.value.operands))) elif isinstance(self.value, Slice): self._hash = hash((ValueKey(self.value.value), self.value.start, self.value.end)) elif isinstance(self.value, Part): @@ -1513,7 +1519,7 @@ class ValueKey: elif isinstance(self.value, (ClockSignal, ResetSignal)): return self.value.domain == other.value.domain elif isinstance(self.value, Operator): - return (self.value.op == other.value.op and + return (self.value.operator == other.value.operator and len(self.value.operands) == len(other.value.operands) and all(ValueKey(a) == ValueKey(b) for a, b in zip(self.value.operands, other.value.operands))) diff --git a/nmigen/hdl/xfrm.py b/nmigen/hdl/xfrm.py index 4e3b9c9..018b368 100644 --- a/nmigen/hdl/xfrm.py +++ b/nmigen/hdl/xfrm.py @@ -157,7 +157,7 @@ class ValueTransformer(ValueVisitor): return value def on_Operator(self, value): - return Operator(value.op, [self.on_value(o) for o in value.operands]) + return Operator(value.operator, [self.on_value(o) for o in value.operands]) def on_Slice(self, value): return Slice(self.on_value(value.value), value.start, value.end)