mirror of https://github.com/llvm/circt.git
[RTL] Signed Math and comparisons (#279)
Add signed comparisons, arithmetic (signed) shift right, and signed math ops firrtl to rtl should use the fancy new signed ops match firrtl lowering semantics: had to check with the firrtl expert about the truncate in rem lowering for signed types
This commit is contained in:
parent
1cdeeb783d
commit
86c0be773a
|
@ -100,10 +100,13 @@ class UTVariadicRTLOp<string mnemonic, list<OpTrait> traits = []> :
|
|||
def AddOp : UTVariadicRTLOp<"add", [Commutative]>;
|
||||
def SubOp : UTBinRTLOp<"sub">;
|
||||
def MulOp : UTVariadicRTLOp<"mul", [Commutative]>;
|
||||
def DivOp : UTBinRTLOp<"div">;
|
||||
def ModOp : UTBinRTLOp<"mod">;
|
||||
def DivUOp : UTBinRTLOp<"divu">;
|
||||
def DivSOp : UTBinRTLOp<"divs">;
|
||||
def ModUOp : UTBinRTLOp<"modu">;
|
||||
def ModSOp : UTBinRTLOp<"mods">;
|
||||
def ShlOp : UTBinRTLOp<"shl">;
|
||||
def ShrOp : UTBinRTLOp<"shr">;
|
||||
def ShrUOp : UTBinRTLOp<"shru">;
|
||||
def ShrSOp : UTBinRTLOp<"shrs">;
|
||||
|
||||
def AndOp : UTVariadicRTLOp<"and", [Commutative]>;
|
||||
def OrOp : UTVariadicRTLOp<"or", [Commutative]>;
|
||||
|
|
|
@ -23,7 +23,8 @@ public:
|
|||
return TypeSwitch<Operation *, ResultType>(op)
|
||||
.template Case<ConstantOp,
|
||||
// Arithmetic and Logical Binary Operations.
|
||||
AddOp, SubOp, MulOp, DivOp, ModOp, ShlOp, ShrOp,
|
||||
AddOp, SubOp, MulOp, DivUOp, DivSOp, ModUOp, ModSOp,
|
||||
ShlOp, ShrUOp, ShrSOp,
|
||||
// Bitwise operations
|
||||
AndOp, OrOp, XorOp,
|
||||
// Comparison operations
|
||||
|
@ -73,16 +74,19 @@ public:
|
|||
}
|
||||
|
||||
// Basic nodes.
|
||||
HANDLE(ConstantOp, Unhandled)
|
||||
HANDLE(ConstantOp, Unhandled);
|
||||
|
||||
// Arithmetic and Logical Binary Operations.
|
||||
HANDLE(AddOp, Binary);
|
||||
HANDLE(SubOp, Binary);
|
||||
HANDLE(MulOp, Binary);
|
||||
HANDLE(DivOp, Binary);
|
||||
HANDLE(ModOp, Binary);
|
||||
HANDLE(DivUOp, Binary);
|
||||
HANDLE(DivSOp, Binary);
|
||||
HANDLE(ModUOp, Binary);
|
||||
HANDLE(ModSOp, Binary);
|
||||
HANDLE(ShlOp, Binary);
|
||||
HANDLE(ShrOp, Binary);
|
||||
HANDLE(ShrUOp, Binary);
|
||||
HANDLE(ShrSOp, Binary);
|
||||
|
||||
HANDLE(AndOp, Variadic);
|
||||
HANDLE(OrOp, Variadic);
|
||||
|
|
|
@ -536,7 +536,8 @@ struct FIRRTLLowering : public LowerFIRRTLToRTLBase<FIRRTLLowering>,
|
|||
|
||||
// Binary Ops.
|
||||
|
||||
template <typename ResultOpType>
|
||||
template <typename ResultUnsignedOpType,
|
||||
typename ResultSignedOpType = ResultUnsignedOpType>
|
||||
LogicalResult lowerBinOp(Operation *op);
|
||||
template <typename ResultOpType>
|
||||
LogicalResult lowerBinOpToVariadic(Operation *op);
|
||||
|
@ -580,7 +581,9 @@ struct FIRRTLLowering : public LowerFIRRTLToRTLBase<FIRRTLLowering>,
|
|||
LogicalResult visitExpr(MulPrimOp op) {
|
||||
return lowerBinOpToVariadic<rtl::MulOp>(op);
|
||||
}
|
||||
LogicalResult visitExpr(DivPrimOp op) { return lowerBinOp<rtl::DivOp>(op); }
|
||||
LogicalResult visitExpr(DivPrimOp op) {
|
||||
return lowerBinOp<rtl::DivUOp, rtl::DivSOp>(op);
|
||||
}
|
||||
LogicalResult visitExpr(RemPrimOp op);
|
||||
|
||||
// Other Operations
|
||||
|
@ -956,7 +959,7 @@ LogicalResult FIRRTLLowering::lowerBinOpToVariadic(Operation *op) {
|
|||
|
||||
/// lowerBinOp extends each operand to the destination type, then performs the
|
||||
/// specified binary operator.
|
||||
template <typename ResultOpType>
|
||||
template <typename ResultUnsignedOpType, typename ResultSignedOpType>
|
||||
LogicalResult FIRRTLLowering::lowerBinOp(Operation *op) {
|
||||
// Extend the two operands to match the destination type.
|
||||
auto resultType = op->getResult(0).getType();
|
||||
|
@ -966,7 +969,9 @@ LogicalResult FIRRTLLowering::lowerBinOp(Operation *op) {
|
|||
return failure();
|
||||
|
||||
// Emit the result operation.
|
||||
return setLoweringTo<ResultOpType>(op, lhs, rhs);
|
||||
if (resultType.cast<IntType>().isSigned())
|
||||
return setLoweringTo<ResultSignedOpType>(op, lhs, rhs);
|
||||
return setLoweringTo<ResultUnsignedOpType>(op, lhs, rhs);
|
||||
}
|
||||
|
||||
/// lowerCmpOp extends each operand to the longest type, then performs the
|
||||
|
@ -1003,10 +1008,17 @@ LogicalResult FIRRTLLowering::visitExpr(CatPrimOp op) {
|
|||
}
|
||||
|
||||
LogicalResult FIRRTLLowering::visitExpr(RemPrimOp op) {
|
||||
// FIRRTL has the width of (a % b) = Min(W(a), W(b)) so we need to truncate
|
||||
// operands to the minimum width before doing the mod, not extend them.
|
||||
auto lhs = getLoweredValue(op.lhs());
|
||||
auto rhs = getLoweredValue(op.rhs());
|
||||
// FIRRTL has the width of (a % b) = Min(W(a), W(b)), but the operation is
|
||||
// done at max(W(a), W(b))) so we need to extend one operand, then truncate
|
||||
// the result.
|
||||
auto lhsFirTy = op.lhs().getType().dyn_cast<IntType>();
|
||||
auto rhsFirTy = op.rhs().getType().dyn_cast<IntType>();
|
||||
if (!lhsFirTy || !rhsFirTy || !lhsFirTy.hasWidth() || !rhsFirTy.hasWidth())
|
||||
return failure();
|
||||
auto opType = lhsFirTy.getWidth() > rhsFirTy.getWidth() ? lhsFirTy : rhsFirTy;
|
||||
|
||||
auto lhs = getLoweredAndExtendedValue(op.lhs(), opType);
|
||||
auto rhs = getLoweredAndExtendedValue(op.rhs(), opType);
|
||||
if (!lhs || !rhs)
|
||||
return failure();
|
||||
|
||||
|
@ -1016,13 +1028,13 @@ LogicalResult FIRRTLLowering::visitExpr(RemPrimOp op) {
|
|||
auto destWidth = unsigned(resultFirType.getWidthOrSentinel());
|
||||
auto resultType = builder->getIntegerType(destWidth);
|
||||
|
||||
// Truncate either operand if required.
|
||||
if (lhs.getType().cast<IntegerType>().getWidth() != destWidth)
|
||||
lhs = builder->create<rtl::ExtractOp>(resultType, lhs, 0);
|
||||
if (rhs.getType().cast<IntegerType>().getWidth() != destWidth)
|
||||
rhs = builder->create<rtl::ExtractOp>(resultType, rhs, 0);
|
||||
|
||||
return setLoweringTo<rtl::ModOp>(op, ValueRange({lhs, rhs}));
|
||||
Value modInst;
|
||||
if (resultFirType.isUnsigned()) {
|
||||
modInst = builder->create<rtl::ModUOp>(ValueRange({lhs, rhs}));
|
||||
} else {
|
||||
modInst = builder->create<rtl::ModSOp>(ValueRange({lhs, rhs}));
|
||||
}
|
||||
return setLoweringTo<rtl::ExtractOp>(op, resultType, modInst, 0);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1109,7 +1121,7 @@ LogicalResult FIRRTLLowering::visitExpr(DShrPrimOp op) {
|
|||
|
||||
// Zero extend or truncate the shift amount if needed.
|
||||
rhs = zeroExtendOrTruncate(rhs, lhs.getType(), *builder);
|
||||
return setLoweringTo<rtl::ShrOp>(op, lhs, rhs);
|
||||
return setLoweringTo<rtl::ShrUOp>(op, lhs, rhs);
|
||||
}
|
||||
|
||||
LogicalResult FIRRTLLowering::visitExpr(TailPrimOp op) {
|
||||
|
|
|
@ -711,7 +711,8 @@ public:
|
|||
private:
|
||||
/// Emit the specified value as a subexpression to the stream.
|
||||
SubExprInfo emitSubExpr(Value exp, VerilogPrecedence parenthesizeIfLooserThan,
|
||||
bool forceExpectedSign = false);
|
||||
bool forceExpectedSign = false,
|
||||
bool opForceSign = false);
|
||||
|
||||
SubExprInfo visitUnhandledExpr(Operation *op);
|
||||
SubExprInfo visitInvalidExpr(Operation *op) {
|
||||
|
@ -738,10 +739,15 @@ private:
|
|||
SubExprInfo emitBitSelect(Value operand, unsigned hiBit, unsigned loBit);
|
||||
|
||||
SubExprInfo emitBinary(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax, bool hasStrictSign = false);
|
||||
const char *syntax, bool hasStrictSign = false,
|
||||
bool opForceSign = false);
|
||||
|
||||
SubExprInfo emitVariadic(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax, bool hasStrictSign = false);
|
||||
const char *syntax, bool hasStrictSign = false,
|
||||
bool opForceSign = false);
|
||||
|
||||
SubExprInfo emitRTLSignedVariadic(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax);
|
||||
|
||||
/// Emit the specified subexpression in a context where the sign matters,
|
||||
/// e.g. for a less than comparison or divide.
|
||||
|
@ -749,6 +755,13 @@ private:
|
|||
const char *syntax) {
|
||||
return emitBinary(op, prec, syntax, /*hasStrictSign:*/ true);
|
||||
}
|
||||
/// Emit the specified subexpression in a context where the sign matters,
|
||||
/// e.g. for a less than comparison or divide.
|
||||
SubExprInfo emitRTLSignedBinary(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax) {
|
||||
return emitBinary(op, prec, syntax, /*hasStrictSign:*/ true,
|
||||
/*opForceSign*/ true);
|
||||
}
|
||||
SubExprInfo emitUnary(Operation *op, const char *syntax, bool forceUnsigned) {
|
||||
os << syntax;
|
||||
auto signedness = emitSubExpr(op->getOperand(0), Unary).signedness;
|
||||
|
@ -856,17 +869,22 @@ private:
|
|||
SubExprInfo visitComb(rtl::MulOp op) {
|
||||
return emitVariadic(op, Multiply, "*");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::DivOp op) {
|
||||
return emitSignedBinary(op, Multiply, "/");
|
||||
SubExprInfo visitComb(rtl::DivUOp op) {
|
||||
return emitBinary(op, Multiply, "/");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::ModOp op) {
|
||||
return emitSignedBinary(op, Multiply, "%");
|
||||
SubExprInfo visitComb(rtl::DivSOp op) {
|
||||
return emitRTLSignedBinary(op, Multiply, "/");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::ShlOp op) {
|
||||
return emitSignedBinary(op, Shift, "<<");
|
||||
SubExprInfo visitComb(rtl::ModUOp op) {
|
||||
return emitBinary(op, Multiply, "%");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::ShrOp op) {
|
||||
return emitSignedBinary(op, Shift, ">>>");
|
||||
SubExprInfo visitComb(rtl::ModSOp op) {
|
||||
return emitRTLSignedBinary(op, Multiply, "%");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::ShlOp op) { return emitBinary(op, Shift, "<<"); }
|
||||
SubExprInfo visitComb(rtl::ShrUOp op) { return emitBinary(op, Shift, ">>>"); }
|
||||
SubExprInfo visitComb(rtl::ShrSOp op) {
|
||||
return emitRTLSignedBinary(op, Shift, ">>>");
|
||||
}
|
||||
SubExprInfo visitComb(rtl::AndOp op) { return emitVariadic(op, And, "&"); }
|
||||
SubExprInfo visitComb(rtl::OrOp op) { return emitVariadic(op, Or, "|"); }
|
||||
|
@ -883,10 +901,15 @@ private:
|
|||
|
||||
// RTL Comparison Operations
|
||||
SubExprInfo visitComb(rtl::ICmpOp op) {
|
||||
std::array<const char *, 10> symop{"==", "!=", "<", "<=", "<",
|
||||
"<=", ">", ">=", ">", ">="};
|
||||
return emitSignedBinary(op, Comparison,
|
||||
symop[static_cast<uint64_t>(op.predicate())]);
|
||||
std::array<const char *, 10> symop{"==", "!=", "<", "<=", ">",
|
||||
">=", "<", "<=", ">", ">="};
|
||||
std::array<bool, 10> signop{false, false, true, true, true,
|
||||
true, false, false, false, false};
|
||||
auto pred = static_cast<uint64_t>(op.predicate());
|
||||
auto symopstr = symop[pred];
|
||||
if (signop[pred])
|
||||
return emitRTLSignedBinary(op, Comparison, symopstr);
|
||||
return emitBinary(op, Comparison, symopstr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -918,8 +941,10 @@ std::string ExprEmitter::emitExpressionToString(Value exp,
|
|||
}
|
||||
|
||||
SubExprInfo ExprEmitter::emitBinary(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax, bool hasStrictSign) {
|
||||
auto lhsInfo = emitSubExpr(op->getOperand(0), prec, hasStrictSign);
|
||||
const char *syntax, bool hasStrictSign,
|
||||
bool opForceSign) {
|
||||
auto lhsInfo =
|
||||
emitSubExpr(op->getOperand(0), prec, hasStrictSign, opForceSign);
|
||||
os << ' ' << syntax << ' ';
|
||||
|
||||
// The precedence of the RHS operand must be tighter than this operator if
|
||||
|
@ -932,12 +957,15 @@ SubExprInfo ExprEmitter::emitBinary(Operation *op, VerilogPrecedence prec,
|
|||
if (rhsOperandOp && op->getName() == rhsOperandOp->getName())
|
||||
rhsPrec = prec;
|
||||
|
||||
auto rhsInfo = emitSubExpr(op->getOperand(1), rhsPrec, hasStrictSign);
|
||||
auto rhsInfo =
|
||||
emitSubExpr(op->getOperand(1), rhsPrec, hasStrictSign, opForceSign);
|
||||
|
||||
// If we have a strict sign, then match the firrtl operation sign.
|
||||
// Otherwise, the result is signed if both operands are signed.
|
||||
SubExprSignedness signedness;
|
||||
if (hasStrictSign)
|
||||
if (opForceSign)
|
||||
signedness = IsSigned;
|
||||
else if (hasStrictSign)
|
||||
signedness = getSignednessOf(op->getResult(0).getType());
|
||||
else if (lhsInfo.signedness == IsSigned && rhsInfo.signedness == IsSigned)
|
||||
signedness = IsSigned;
|
||||
|
@ -948,19 +976,26 @@ SubExprInfo ExprEmitter::emitBinary(Operation *op, VerilogPrecedence prec,
|
|||
}
|
||||
|
||||
SubExprInfo ExprEmitter::emitVariadic(Operation *op, VerilogPrecedence prec,
|
||||
const char *syntax, bool hasStrictSign) {
|
||||
const char *syntax, bool hasStrictSign,
|
||||
bool opForceSign) {
|
||||
interleave(
|
||||
op->getOperands().begin(), op->getOperands().end(),
|
||||
[&](Value v1) { emitSubExpr(v1, prec, hasStrictSign); },
|
||||
[&](Value v1) { emitSubExpr(v1, prec, hasStrictSign, opForceSign); },
|
||||
[&] { os << ' ' << syntax << ' '; });
|
||||
|
||||
return {prec, IsUnsigned};
|
||||
}
|
||||
|
||||
SubExprInfo ExprEmitter::emitRTLSignedVariadic(Operation *op,
|
||||
VerilogPrecedence prec,
|
||||
const char *syntax) {
|
||||
return emitVariadic(op, prec, syntax, true, true);
|
||||
}
|
||||
|
||||
/// Emit the specified value as a subexpression to the stream.
|
||||
SubExprInfo ExprEmitter::emitSubExpr(Value exp,
|
||||
VerilogPrecedence parenthesizeIfLooserThan,
|
||||
bool forceExpectedSign) {
|
||||
bool forceExpectedSign, bool opForceSign) {
|
||||
auto *op = exp.getDefiningOp();
|
||||
bool shouldEmitInlineExpr = op && isVerilogExpression(op);
|
||||
|
||||
|
@ -972,7 +1007,8 @@ SubExprInfo ExprEmitter::emitSubExpr(Value exp,
|
|||
// If this is a non-expr or shouldn't be done inline, just refer to its
|
||||
// name.
|
||||
if (!shouldEmitInlineExpr) {
|
||||
if (forceExpectedSign && getSignednessOf(exp.getType()) != IsUnsigned) {
|
||||
if ((forceExpectedSign && getSignednessOf(exp.getType()) != IsUnsigned) ||
|
||||
opForceSign) {
|
||||
os << "$signed(" << emitter.getName(exp) << ')';
|
||||
return {Unary, IsSigned};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ firrtl.circuit "M1" {
|
|||
firrtl.connect %y, %c : !firrtl.flip<uint<8>>, !firrtl.uint<8>
|
||||
|
||||
%d = rtl.mul %z, %z, %z : i8
|
||||
%e = rtl.mod %d, %c5 : i8
|
||||
%e = rtl.modu %d, %c5 : i8
|
||||
%f = rtl.concat %e, %z, %d : (i8, i8, i8) -> i8
|
||||
%g = firrtl.stdIntCast %f : (i8) -> !firrtl.uint<8>
|
||||
firrtl.connect %y, %g : !firrtl.flip<uint<8>>, !firrtl.uint<8>
|
||||
|
|
|
@ -7,87 +7,95 @@ module {
|
|||
|
||||
// CHECK-LABEL: // external module E
|
||||
|
||||
rtl.module @TESTSIMPLE(%a: i4, %cond: i1) -> (%r0: i4, %r1: i4, %r2: i4, %r3: i4, %r4: i4, %r5: i4, %r6: i4, %r7: i4, %r8: i4, %r9: i4,
|
||||
%r10: i1, %r11: i1, %r12: i1, %r13: i1, %r14: i1, %r15: i1, %r16: i1, %r17: i1, %r18: i1, %r19: i1,
|
||||
%r20: i1, %r21: i1, %r22: i1, %r23: i12, %r24: i2, %r25: i9, %r26: i9, %r27: i4
|
||||
) {
|
||||
%0 = rtl.add %a, %a : i4
|
||||
%1 = rtl.sub %a, %a : i4
|
||||
%2 = rtl.mul %a, %a : i4
|
||||
%3 = rtl.div %a, %a : i4
|
||||
%4 = rtl.mod %a, %a : i4
|
||||
%5 = rtl.shl %a, %a : i4
|
||||
%6 = rtl.shr %a, %a : i4
|
||||
%7 = rtl.or %a, %a : i4
|
||||
%8 = rtl.and %a, %a : i4
|
||||
%9 = rtl.xor %a, %a : i4
|
||||
%10 = rtl.icmp "eq" %a, %a : i4
|
||||
%11 = rtl.icmp "ne" %a, %a : i4
|
||||
%12 = rtl.icmp "slt" %a, %a : i4
|
||||
%13 = rtl.icmp "sle" %a, %a : i4
|
||||
%14 = rtl.icmp "sgt" %a, %a : i4
|
||||
%15 = rtl.icmp "sge" %a, %a : i4
|
||||
%16 = rtl.icmp "ult" %a, %a : i4
|
||||
%17 = rtl.icmp "ule" %a, %a : i4
|
||||
%18 = rtl.icmp "ugt" %a, %a : i4
|
||||
%19 = rtl.icmp "uge" %a, %a : i4
|
||||
%20 = rtl.andr %a : i4
|
||||
%21 = rtl.orr %a : i4
|
||||
%22 = rtl.xorr %a : i4
|
||||
%23 = rtl.concat %a, %a, %a : (i4, i4, i4) -> i12
|
||||
%24 = rtl.extract %a from 1 : (i4) -> i2
|
||||
%25 = rtl.sext %a : (i4) -> i9
|
||||
%26 = rtl.zext %a : (i4) -> i9
|
||||
%27 = rtl.mux %cond, %a, %a : i4
|
||||
rtl.module @TESTSIMPLE(%a: i4, %b: i4, %cond: i1) -> (
|
||||
%r0: i4, %r2: i4, %r4: i4, %r6: i4,
|
||||
%r7: i4, %r8: i4, %r9: i4, %r10: i4,
|
||||
%r11: i4, %r12: i4, %r13: i4, %r14: i4,
|
||||
%r15: i4, %r16: i1,
|
||||
%r17: i1, %r18: i1, %r19: i1, %r20: i1,
|
||||
%r21: i1, %r22: i1, %r23: i1, %r24: i1,
|
||||
%r25: i1, %r26: i1, %r27: i1, %r28: i1,
|
||||
%r29: i12, %r30: i2, %r31: i9, %r32: i9, %r33: i4
|
||||
) {
|
||||
|
||||
rtl.output %0, %1, %2, %3, %4, %5, %6, %7, %8, %9,
|
||||
%10, %11, %12, %13, %14, %15, %16, %17, %18, %19,
|
||||
%20, %21, %22, %23, %24, %25, %26, %27 :
|
||||
i4, i4, i4, i4, i4,
|
||||
i4, i4, i4, i4, i4,
|
||||
i1, i1, i1, i1, i1,
|
||||
i1, i1, i1, i1, i1,
|
||||
i1, i1, i1, i12, i2,
|
||||
i9, i9, i4
|
||||
%0 = rtl.add %a, %b : i4
|
||||
%2 = rtl.sub %a, %b : i4
|
||||
%4 = rtl.mul %a, %b : i4
|
||||
%6 = rtl.divu %a, %b : i4
|
||||
%7 = rtl.divs %a, %b : i4
|
||||
%8 = rtl.modu %a, %b : i4
|
||||
%9 = rtl.mods %a, %b : i4
|
||||
%10 = rtl.shl %a, %b : i4
|
||||
%11 = rtl.shru %a, %b : i4
|
||||
%12 = rtl.shrs %a, %b : i4
|
||||
%13 = rtl.or %a, %b : i4
|
||||
%14 = rtl.and %a, %b : i4
|
||||
%15 = rtl.xor %a, %b : i4
|
||||
%16 = rtl.icmp "eq" %a, %b : i4
|
||||
%17 = rtl.icmp "ne" %a, %b : i4
|
||||
%18 = rtl.icmp "slt" %a, %b : i4
|
||||
%19 = rtl.icmp "sle" %a, %b : i4
|
||||
%20 = rtl.icmp "sgt" %a, %b : i4
|
||||
%21 = rtl.icmp "sge" %a, %b : i4
|
||||
%22 = rtl.icmp "ult" %a, %b : i4
|
||||
%23 = rtl.icmp "ule" %a, %b : i4
|
||||
%24 = rtl.icmp "ugt" %a, %b : i4
|
||||
%25 = rtl.icmp "uge" %a, %b : i4
|
||||
%26 = rtl.andr %a : i4
|
||||
%27 = rtl.orr %a : i4
|
||||
%28 = rtl.xorr %a : i4
|
||||
%29 = rtl.concat %a, %a, %b : (i4, i4, i4) -> i12
|
||||
%30 = rtl.extract %a from 1 : (i4) -> i2
|
||||
%31 = rtl.sext %a : (i4) -> i9
|
||||
%32 = rtl.zext %a : (i4) -> i9
|
||||
%33 = rtl.mux %cond, %a, %b : i4
|
||||
|
||||
rtl.output %0, %2, %4, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16, %17, %18, %19, %20, %21, %22, %23, %24, %25, %26, %27, %28, %29, %30, %31, %32, %33:
|
||||
i4,i4, i4,i4,i4,i4,i4, i4,i4,i4,i4,i4,
|
||||
i4,i1,i1,i1,i1, i1,i1,i1,i1,i1, i1,i1,i1,i1,
|
||||
i12, i2,i9,i9,i4
|
||||
}
|
||||
// CHECK-LABEL: module TESTSIMPLE(
|
||||
// CHECK-NEXT: input [3:0] a,
|
||||
// CHECK-NEXT: input [3:0] a, b
|
||||
// CHECK-NEXT: input cond,
|
||||
// CHECK-NEXT: output [3:0] r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,
|
||||
// CHECK-NEXT: output r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22,
|
||||
// CHECK-NEXT: output [11:0] r23,
|
||||
// CHECK-NEXT: output [1:0] r24,
|
||||
// CHECK-NEXT: output [8:0] r25, r26,
|
||||
// CHECK-NEXT: output [3:0] r27);
|
||||
// CHECK-NEXT: output [3:0] r0, r2, r4, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15
|
||||
// CHECK-NEXT: output r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28
|
||||
// CHECK-NEXT: output [11:0] r29,
|
||||
// CHECK-NEXT: output [1:0] r30,
|
||||
// CHECK-NEXT: output [8:0] r31, r32,
|
||||
// CHECK-NEXT: output [3:0] r33);
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: assign r0 = a + a;
|
||||
// CHECK-NEXT: assign r1 = a - a;
|
||||
// CHECK-NEXT: assign r2 = a * a;
|
||||
// CHECK-NEXT: assign r3 = a / a;
|
||||
// CHECK-NEXT: assign r4 = a % a;
|
||||
// CHECK-NEXT: assign r5 = a << a;
|
||||
// CHECK-NEXT: assign r6 = a >>> a;
|
||||
// CHECK-NEXT: assign r7 = a | a;
|
||||
// CHECK-NEXT: assign r8 = a & a;
|
||||
// CHECK-NEXT: assign r9 = a ^ a;
|
||||
// CHECK-NEXT: assign r10 = a == a;
|
||||
// CHECK-NEXT: assign r11 = a != a;
|
||||
// CHECK-NEXT: assign r12 = a < a;
|
||||
// CHECK-NEXT: assign r13 = a <= a;
|
||||
// CHECK-NEXT: assign r14 = a < a;
|
||||
// CHECK-NEXT: assign r15 = a <= a;
|
||||
// CHECK-NEXT: assign r16 = a > a;
|
||||
// CHECK-NEXT: assign r17 = a >= a;
|
||||
// CHECK-NEXT: assign r18 = a > a;
|
||||
// CHECK-NEXT: assign r19 = a >= a;
|
||||
// CHECK-NEXT: assign r20 = &a;
|
||||
// CHECK-NEXT: assign r21 = |a;
|
||||
// CHECK-NEXT: assign r22 = ^a;
|
||||
// CHECK-NEXT: assign r23 = {a, a, a};
|
||||
// CHECK-NEXT: assign r24 = a[2:1];
|
||||
// CHECK-NEXT: assign r25 = {{[{}][{}]}}5{a[3]}}, a};
|
||||
// CHECK-NEXT: assign r26 = {{[{}][{}]}}5'd0}, a};
|
||||
// CHECK-NEXT: assign r27 = cond ? a : a;
|
||||
// CHECK-NEXT: assign r0 = a + b;
|
||||
// CHECK-NEXT: assign r2 = a - b;
|
||||
// CHECK-NEXT: assign r4 = a * b;
|
||||
// CHECK-NEXT: assign r6 = a / b;
|
||||
// CHECK-NEXT: assign r7 = $signed(a) / $signed(b);
|
||||
// CHECK-NEXT: assign r8 = a % b;
|
||||
// CHECK-NEXT: assign r9 = $signed(a) % $signed(b);
|
||||
// CHECK-NEXT: assign r10 = a << b;
|
||||
// CHECK-NEXT: assign r11 = a >>> b;
|
||||
// CHECK-NEXT: assign r12 = $signed(a) >>> $signed(b);
|
||||
// CHECK-NEXT: assign r13 = a | b;
|
||||
// CHECK-NEXT: assign r14 = a & b;
|
||||
// CHECK-NEXT: assign r15 = a ^ b;
|
||||
// CHECK-NEXT: assign r16 = a == b;
|
||||
// CHECK-NEXT: assign r17 = a != b;
|
||||
// CHECK-NEXT: assign r18 = $signed(a) < $signed(b);
|
||||
// CHECK-NEXT: assign r19 = $signed(a) <= $signed(b);
|
||||
// CHECK-NEXT: assign r20 = $signed(a) > $signed(b);
|
||||
// CHECK-NEXT: assign r21 = $signed(a) >= $signed(b);
|
||||
// CHECK-NEXT: assign r22 = a < b;
|
||||
// CHECK-NEXT: assign r23 = a <= b;
|
||||
// CHECK-NEXT: assign r24 = a > b;
|
||||
// CHECK-NEXT: assign r25 = a >= b;
|
||||
// CHECK-NEXT: assign r26 = &a;
|
||||
// CHECK-NEXT: assign r27 = |a;
|
||||
// CHECK-NEXT: assign r28 = ^a;
|
||||
// CHECK-NEXT: assign r29 = {a, a, b};
|
||||
// CHECK-NEXT: assign r30 = a[2:1];
|
||||
// CHECK-NEXT: assign r31 = {{[{}][{}]}}5{a[3]}}, a};
|
||||
// CHECK-NEXT: assign r32 = {{[{}][{}]}}5'd0}, a};
|
||||
// CHECK-NEXT: assign r33 = cond ? a : b;
|
||||
// CHECK-NEXT: endmodule
|
||||
|
||||
rtl.module @B(%a: i1 { rtl.inout }) -> (%b: i1, %c: i1) {
|
||||
|
|
|
@ -103,20 +103,22 @@ module attributes {firrtl.mainModule = "Simple"} {
|
|||
|
||||
// CHECK-NEXT: [[ZEXTC1:%.+]] = rtl.zext [[CONCAT1]] : (i8) -> i12
|
||||
// CHECK-NEXT: [[ZEXT2:%.+]] = rtl.zext [[SUB]] : (i4) -> i12
|
||||
// CHECK-NEXT: [[VAL18:%.+]] = rtl.mul [[ZEXTC1]], [[ZEXT2]] : i12
|
||||
// CHECK-NEXT: [[VAL18:%.+]] = rtl.mul [[ZEXTC1]], [[ZEXT2]] : i12
|
||||
%18 = firrtl.mul %6, %2 : (!firrtl.uint<8>, !firrtl.uint<4>) -> !firrtl.uint<12>
|
||||
|
||||
// CHECK-NEXT: [[IN3SEXT:%.+]] = rtl.sext %in3 : (i8) -> i9
|
||||
// CHECK-NEXT: [[PADRESSEXT:%.+]] = rtl.sext [[PADRES]] : (i3) -> i9
|
||||
// CHECK-NEXT: = rtl.div [[IN3SEXT]], [[PADRESSEXT]] : i9
|
||||
// CHECK-NEXT: = rtl.divs [[IN3SEXT]], [[PADRESSEXT]] : i9
|
||||
%19 = firrtl.div %in3c, %3 : (!firrtl.sint<8>, !firrtl.sint<3>) -> !firrtl.sint<9>
|
||||
|
||||
// CHECK-NEXT: [[IN3TRUNC:%.+]] = rtl.extract %in3 from 0 : (i8) -> i3
|
||||
// CHECK-NEXT: = rtl.mod [[IN3TRUNC]], [[PADRES]] : i3
|
||||
// CHECK-NEXT: [[IN3EX:%.+]] = rtl.sext [[PADRES]] : (i3) -> i8
|
||||
// CHECK-NEXT: [[MOD1:%.+]] = rtl.mods %in3, [[IN3EX]] : i8
|
||||
// CHECK-NEXT: = rtl.extract [[MOD1]] from 0 : (i8) -> i3
|
||||
%20 = firrtl.rem %in3c, %3 : (!firrtl.sint<8>, !firrtl.sint<3>) -> !firrtl.sint<3>
|
||||
|
||||
// CHECK-NEXT: [[IN3TRUNC:%.+]] = rtl.extract %in3 from 0 : (i8) -> i3
|
||||
// CHECK-NEXT: = rtl.mod [[PADRES]], [[IN3TRUNC]] : i3
|
||||
// CHECK-NEXT: [[IN4EX:%.+]] = rtl.sext [[PADRES]] : (i3) -> i8
|
||||
// CHECK-NEXT: [[MOD2:%.+]] = rtl.mods [[IN4EX]], %in3 : i8
|
||||
// CHECK-NEXT: = rtl.extract [[MOD2]] from 0 : (i8) -> i3
|
||||
%21 = firrtl.rem %3, %in3c : (!firrtl.sint<3>, !firrtl.sint<8>) -> !firrtl.sint<3>
|
||||
|
||||
// CHECK-NEXT: [[WIRE:%n1]] = rtl.wire : i2
|
||||
|
@ -151,7 +153,7 @@ module attributes {firrtl.mainModule = "Simple"} {
|
|||
%28 = firrtl.andr %27 : (!firrtl.uint<12>) -> !firrtl.uint<1>
|
||||
|
||||
// CHECK-NEXT: = rtl.extract [[VAL18]] from 0 : (i12) -> i3
|
||||
// CHECK-NEXT: = rtl.shr [[XOR]], {{.*}} : i3
|
||||
// CHECK-NEXT: = rtl.shru [[XOR]], {{.*}} : i3
|
||||
%29 = firrtl.dshr %24, %18 : (!firrtl.uint<3>, !firrtl.uint<12>) -> !firrtl.uint<3>
|
||||
|
||||
// CHECK-NEXT: = rtl.zext %2 : (i3) -> i8
|
||||
|
|
|
@ -26,8 +26,8 @@ func @shl_op(%a: i7, %b: i7) -> i7 {
|
|||
|
||||
// CHECK-LABEL: func @shr_op(%arg0: i7, %arg1: i7) -> i7 {
|
||||
func @shr_op(%a: i7, %b: i7) -> i7 {
|
||||
// CHECK-NEXT: [[RES:%[0-9]+]] = rtl.shr %arg0, %arg1 : i7
|
||||
%0 = rtl.shr %a, %b : i7
|
||||
// CHECK-NEXT: [[RES:%[0-9]+]] = rtl.shru %arg0, %arg1 : i7
|
||||
%0 = rtl.shru %a, %b : i7
|
||||
// CHECK-NEXT: return [[RES]]
|
||||
return %0 : i7
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue