[ImportVerilog] Support the power operator (#7395)

Add support for the `**` operator.
This commit is contained in:
Fabian Schuiki 2024-07-27 14:05:55 -07:00 committed by GitHub
parent 0b72b19b8d
commit 756166e6ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 3 deletions

View File

@ -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 = [{

View File

@ -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");

View File

@ -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