mirror of https://github.com/llvm/circt.git
[ImportVerilog] Support the power operator (#7395)
Add support for the `**` operator.
This commit is contained in:
parent
0b72b19b8d
commit
756166e6ee
|
@ -646,6 +646,28 @@ class ModOpBase<string mnemonic> : BinaryOpBase<mnemonic> {
|
|||
def ModUOp : ModOpBase<"modu">;
|
||||
def ModSOp : ModOpBase<"mods">;
|
||||
|
||||
class PowOpBase<string mnemonic> : BinaryOpBase<mnemonic> {
|
||||
let summary = "Power";
|
||||
let description = [{
|
||||
Raise the left-hand side to the power of the right-hand side. `powu` treats
|
||||
its operands as unsigned numbers, while `pows` treats them as signed
|
||||
numbers.
|
||||
|
||||
Evaluation rules for `a ** b`:
|
||||
|
||||
| | a < -1 | a = -1 | a = 0 | a = 1 | a > 1 |
|
||||
|-------|--------|----------------|-------|-------|--------|
|
||||
| b > 0 | a ** b | b odd ? -1 : 1 | 0 | 1 | a ** b |
|
||||
| b = 0 | 1 | 1 | 1 | 1 | 1 |
|
||||
| b < 0 | 0 | b odd ? -1 : 1 | X | 1 | 0 |
|
||||
|
||||
See IEEE 1800-2017 § 11.4.3 "Arithmetic operators".
|
||||
}];
|
||||
}
|
||||
|
||||
def PowUOp : PowOpBase<"powu">;
|
||||
def PowSOp : PowOpBase<"pows">;
|
||||
|
||||
def AndOp : BinaryOpBase<"and", [Commutative]> {
|
||||
let summary = "Bitwise AND operation";
|
||||
let description = [{
|
||||
|
|
|
@ -260,6 +260,18 @@ struct RvalueExprVisitor {
|
|||
return createBinary<moore::ModSOp>(lhs, rhs);
|
||||
else
|
||||
return createBinary<moore::ModUOp>(lhs, rhs);
|
||||
case BinaryOperator::Power: {
|
||||
// Slang casts the LHS and result of the `**` operator to a four-valued
|
||||
// type, since the operator can return X even for two-valued inputs. To
|
||||
// maintain uniform types across operands and results, cast the RHS to
|
||||
// that four-valued type as well.
|
||||
auto rhsCast =
|
||||
builder.create<moore::ConversionOp>(loc, lhs.getType(), rhs);
|
||||
if (expr.type->isSigned())
|
||||
return createBinary<moore::PowSOp>(lhs, rhsCast);
|
||||
else
|
||||
return createBinary<moore::PowUOp>(lhs, rhsCast);
|
||||
}
|
||||
|
||||
case BinaryOperator::BinaryAnd:
|
||||
return createBinary<moore::AndOp>(lhs, rhs);
|
||||
|
@ -364,9 +376,6 @@ struct RvalueExprVisitor {
|
|||
return builder.create<moore::AShrOp>(loc, lhs, rhs);
|
||||
return builder.create<moore::ShrOp>(loc, lhs, rhs);
|
||||
}
|
||||
|
||||
case BinaryOperator::Power:
|
||||
break;
|
||||
}
|
||||
|
||||
mlir::emitError(loc, "unsupported binary operator");
|
||||
|
|
|
@ -442,6 +442,7 @@ module Expressions;
|
|||
// CHECK: %c = moore.variable : <i32>
|
||||
int a, b, c;
|
||||
// CHECK: %u = moore.variable : <i32>
|
||||
// CHECK: %w = moore.variable : <i32>
|
||||
int unsigned u, w;
|
||||
// CHECK: %v = moore.variable : <array<2 x i4>>
|
||||
bit [1:0][3:0] v;
|
||||
|
@ -680,6 +681,20 @@ module Expressions;
|
|||
// CHECK: [[TMP2:%.+]] = moore.read %e
|
||||
// CHECK: moore.mods [[TMP1]], [[TMP2]] : l32
|
||||
f = d % e;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %b
|
||||
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
|
||||
// CHECK: [[TMP1:%.+]] = moore.pows [[TMP2]], [[TMP3]] : l32
|
||||
// CHECK: moore.conversion [[TMP1]] : !moore.l32 -> !moore.i32
|
||||
c = a ** b;
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %u
|
||||
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %w
|
||||
// CHECK: [[TMP3:%.+]] = moore.conversion [[TMP1]] : !moore.i32 -> !moore.l32
|
||||
// CHECK: [[TMP1:%.+]] = moore.powu [[TMP2]], [[TMP3]] : l32
|
||||
// CHECK: moore.conversion [[TMP1]] : !moore.l32 -> !moore.i32
|
||||
u = u ** w;
|
||||
|
||||
// CHECK: [[TMP1:%.+]] = moore.read %a
|
||||
// CHECK: [[TMP2:%.+]] = moore.read %b
|
||||
|
|
Loading…
Reference in New Issue