diff --git a/include/circt/Dialect/Moore/MooreOps.td b/include/circt/Dialect/Moore/MooreOps.td index 2a043e4881c4..db1cf00f2701 100644 --- a/include/circt/Dialect/Moore/MooreOps.td +++ b/include/circt/Dialect/Moore/MooreOps.td @@ -508,6 +508,23 @@ def StringConstantOp : MooreOp<"string_constant", [Pure]> { let assemblyFormat = "$value attr-dict `:` type($result)"; } +def RealLiteralOp : MooreOp<"real_constant", [Pure]> { + let summary = "Produce a constant real value"; + let description = [{ + Produces a constant value of real type. + + Example: + ```mlir + %0 = moore.real_constant 1.23 + ``` + The real type has fixed-point(1.2) and exponent(2.0e10) formats. + See IEEE 1800-2017 § 5.7.2 "Real literal constants". + }]; + let arguments = (ins F64Attr:$value); + let results = (outs RealType:$result); + let assemblyFormat = "$value attr-dict `:` type($result)"; +} + //===----------------------------------------------------------------------===// // Casting and Resizing //===----------------------------------------------------------------------===// @@ -1610,6 +1627,20 @@ def SeverityBIOp : Builtin<"severity"> { // Math Builtins //===----------------------------------------------------------------------===// +class RealMathFunc traits = []> : + Builtin { + let description = [{ + The system real math functions shall accept real value arguments and return + a real result type. Their behavior shall match the equivalent C language + standard math library function indicated. + + See IEEE 1800-2017 § 20.8.2 "Real math functions". + }]; + let arguments = (ins RealType:$value); + let results = (outs RealType:$result); + let assemblyFormat = "$value attr-dict `:` type($value)"; +} + def Clog2BIOp : Builtin<"clog2", [SameOperandsAndResultType]> { let summary = "Compute ceil(log2(x)) of x"; let description = [{ @@ -1628,4 +1659,76 @@ def Clog2BIOp : Builtin<"clog2", [SameOperandsAndResultType]> { let assemblyFormat = "$value attr-dict `:` type($value)"; } +def LnBIOp : RealMathFunc<"ln"> { + let summary = "Natural logarithm"; +} + +def Log10BIOp : RealMathFunc<"log10"> { + let summary = "Decimal logarithm"; +} + +def ExpBIOp : RealMathFunc<"exp"> { + let summary = "Exponential"; +} + +def SqrtBIOp : RealMathFunc<"sqrt"> { + let summary = "Square root"; +} + +def FloorBIOp : RealMathFunc<"floor"> { + let summary = "Floor"; +} + +def CeilBIOp : RealMathFunc<"ceil"> { + let summary = "Ceiling"; +} + +def SinBIOp : RealMathFunc<"sin"> { + let summary = "Sine"; +} + +def CosBIOp : RealMathFunc<"cos"> { + let summary = "Cosine"; +} + +def TanBIOp : RealMathFunc<"tan"> { + let summary = "Tangent"; +} + +def AsinBIOp : RealMathFunc<"asin"> { + let summary = "Arc-sine"; +} + +def AcosBIOp : RealMathFunc<"acos"> { + let summary = "Arc-cosine"; +} + +def AtanBIOp : RealMathFunc<"atan"> { + let summary = "Arc-tangent"; +} + +def SinhBIOp : RealMathFunc<"sinh"> { + let summary = "Hyperbolic sine"; +} + +def CoshBIOp : RealMathFunc<"cosh"> { + let summary = "Hyperbolic cosine"; +} + +def TanhBIOp : RealMathFunc<"tanh"> { + let summary = "Hyperbolic tangent"; +} + +def AsinhBIOp : RealMathFunc<"asinh"> { + let summary = "Arc-hyperbolic sine"; +} + +def AcoshBIOp : RealMathFunc<"acosh"> { + let summary = "Arc-hyperbolic cosine"; +} + +def AtanhBIOp : RealMathFunc<"atanh"> { + let summary = "Arc-hyperbolic tangent"; +} + #endif // CIRCT_DIALECT_MOORE_MOOREOPS diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index 51588f91d52d..6899cfe058d1 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -751,15 +751,15 @@ struct RvalueExprVisitor { const auto &subroutine = *info.subroutine; auto args = expr.arguments(); - if (subroutine.name == "$signed" || subroutine.name == "$unsigned") - return context.convertRvalueExpression(*args[0]); - - if (subroutine.name == "$clog2") { - auto value = context.convertToSimpleBitVector( - context.convertRvalueExpression(*args[0])); + if (args.size() == 1) { + auto value = context.convertRvalueExpression(*args[0]); if (!value) return {}; - return builder.create(loc, value); + auto result = context.convertSystemCallArity1(subroutine, loc, value); + if (failed(result)) + return {}; + if (*result) + return *result; } mlir::emitError(loc) << "unsupported system call `" << subroutine.name @@ -773,6 +773,12 @@ struct RvalueExprVisitor { return builder.create(loc, type, expr.getValue()); } + /// Handle real literals. + Value visit(const slang::ast::RealLiteral &expr) { + return builder.create( + loc, builder.getF64FloatAttr(expr.getValue())); + } + /// Handle assignment patterns. Value visitAssignmentPattern( const slang::ast::AssignmentPatternExpressionBase &expr, @@ -1310,3 +1316,96 @@ Value Context::materializeConversion(Type type, Value value, bool isSigned, value = builder.create(loc, type, value); return value; } + +FailureOr +Context::convertSystemCallArity1(const slang::ast::SystemSubroutine &subroutine, + Location loc, Value value) { + auto systemCallRes = + llvm::StringSwitch()>>(subroutine.name) + // Signed and unsigned system functions. + .Case("$signed", [&]() { return value; }) + .Case("$unsigned", [&]() { return value; }) + + // Math functions in SystemVerilog. + .Case("$clog2", + [&]() -> FailureOr { + value = convertToSimpleBitVector(value); + if (!value) + return failure(); + return (Value)builder.create(loc, value); + }) + .Case("$ln", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$log10", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$sin", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$cos", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$tan", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$exp", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$sqrt", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$floor", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$ceil", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$asin", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$acos", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$atan", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$sinh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$cosh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$tanh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$asinh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$acosh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Case("$atanh", + [&]() -> Value { + return builder.create(loc, value); + }) + .Default([&]() -> Value { return {}; }); + return systemCallRes(); +} diff --git a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h index 431710ca935c..5c2fdd4880d1 100644 --- a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h +++ b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h @@ -163,6 +163,11 @@ struct Context { moore::IntFormat defaultFormat = moore::IntFormat::Decimal, bool appendNewline = false); + /// Convert system function calls only have arity-1. + FailureOr + convertSystemCallArity1(const slang::ast::SystemSubroutine &subroutine, + Location loc, Value value); + /// Evaluate the constant value of an expression. slang::ConstantValue evaluateConstant(const slang::ast::Expression &expr); diff --git a/test/Conversion/ImportVerilog/builtins.sv b/test/Conversion/ImportVerilog/builtins.sv index ae4abbb2d2f2..908935539c2e 100644 --- a/test/Conversion/ImportVerilog/builtins.sv +++ b/test/Conversion/ImportVerilog/builtins.sv @@ -6,6 +6,7 @@ // UNSUPPORTED: valgrind function void dummyA(int x); endfunction +function void dummyB(real x); endfunction // IEEE 1800-2017 § 20.2 "Simulation control system tasks" // CHECK-LABEL: func.func private @SimulationControlBuiltins( @@ -191,9 +192,47 @@ endfunction // CHECK-LABEL: func.func private @MathBuiltins( // CHECK-SAME: [[X:%.+]]: !moore.i32 // CHECK-SAME: [[Y:%.+]]: !moore.l42 -function void MathBuiltins(int x, logic [41:0] y); +// CHECK-SAME: [[R:%.+]]: !moore.real +function void MathBuiltins(int x, logic [41:0] y, real r); // CHECK: moore.builtin.clog2 [[X]] : i32 dummyA($clog2(x)); // CHECK: moore.builtin.clog2 [[Y]] : l42 dummyA($clog2(y)); + + // CHECK: moore.builtin.ln [[R]] : real + dummyB($ln(r)); + // CHECK: moore.builtin.log10 [[R]] : real + dummyB($log10(r)); + // CHECK: moore.builtin.exp [[R]] : real + dummyB($exp(r)); + // CHECK: moore.builtin.sqrt [[R]] : real + dummyB($sqrt(r)); + // CHECK: moore.builtin.floor [[R]] : real + dummyB($floor(r)); + // CHECK: moore.builtin.ceil [[R]] : real + dummyB($ceil(r)); + // CHECK: moore.builtin.sin [[R]] : real + dummyB($sin(r)); + // CHECK: moore.builtin.cos [[R]] : real + dummyB($cos(r)); + // CHECK: moore.builtin.tan [[R]] : real + dummyB($tan(r)); + // CHECK: moore.builtin.asin [[R]] : real + dummyB($asin(r)); + // CHECK: moore.builtin.acos [[R]] : real + dummyB($acos(r)); + // CHECK: moore.builtin.atan [[R]] : real + dummyB($atan(r)); + // CHECK: moore.builtin.sinh [[R]] : real + dummyB($sinh(r)); + // CHECK: moore.builtin.cosh [[R]] : real + dummyB($cosh(r)); + // CHECK: moore.builtin.tanh [[R]] : real + dummyB($tanh(r)); + // CHECK: moore.builtin.asinh [[R]] : real + dummyB($asinh(r)); + // CHECK: moore.builtin.acosh [[R]] : real + dummyB($acosh(r)); + // CHECK: moore.builtin.atanh [[R]] : real + dummyB($atanh(r)); endfunction