Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ImportVerilog]Support real math functions. #8192

Merged
merged 1 commit into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions include/circt/Dialect/Moore/MooreOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)";
}

Comment on lines +511 to +527
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Borrow from #8020 .

//===----------------------------------------------------------------------===//
// Casting and Resizing
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1610,6 +1627,20 @@ def SeverityBIOp : Builtin<"severity"> {
// Math Builtins
//===----------------------------------------------------------------------===//

class RealMathFunc<string mnemonic, list<Trait> traits = []> :
Builtin<mnemonic, traits # [SameOperandsAndResultType]> {
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 = [{
Expand All @@ -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";
}

hailongSun2000 marked this conversation as resolved.
Show resolved Hide resolved
#endif // CIRCT_DIALECT_MOORE_MOOREOPS
113 changes: 106 additions & 7 deletions lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<moore::Clog2BIOp>(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
Expand All @@ -773,6 +773,12 @@ struct RvalueExprVisitor {
return builder.create<moore::StringConstantOp>(loc, type, expr.getValue());
}

/// Handle real literals.
Value visit(const slang::ast::RealLiteral &expr) {
return builder.create<moore::RealLiteralOp>(
loc, builder.getF64FloatAttr(expr.getValue()));
}

/// Handle assignment patterns.
Value visitAssignmentPattern(
const slang::ast::AssignmentPatternExpressionBase &expr,
Expand Down Expand Up @@ -1310,3 +1316,96 @@ Value Context::materializeConversion(Type type, Value value, bool isSigned,
value = builder.create<moore::ConversionOp>(loc, type, value);
return value;
}

FailureOr<Value>
Context::convertSystemCallArity1(const slang::ast::SystemSubroutine &subroutine,
Location loc, Value value) {
auto systemCallRes =
llvm::StringSwitch<std::function<FailureOr<Value>()>>(subroutine.name)
// Signed and unsigned system functions.
.Case("$signed", [&]() { return value; })
.Case("$unsigned", [&]() { return value; })

// Math functions in SystemVerilog.
.Case("$clog2",
[&]() -> FailureOr<Value> {
value = convertToSimpleBitVector(value);
if (!value)
return failure();
return (Value)builder.create<moore::Clog2BIOp>(loc, value);
})
Comment on lines +1330 to +1336
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is reasonable? First time to use std::function<FailureOr<Value>()>. It just looks correct 😂.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 😃

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greatly appreciate your guidance!

.Case("$ln",
[&]() -> Value {
return builder.create<moore::LnBIOp>(loc, value);
})
.Case("$log10",
[&]() -> Value {
return builder.create<moore::Log10BIOp>(loc, value);
})
.Case("$sin",
[&]() -> Value {
return builder.create<moore::SinBIOp>(loc, value);
})
.Case("$cos",
[&]() -> Value {
return builder.create<moore::CosBIOp>(loc, value);
})
.Case("$tan",
[&]() -> Value {
return builder.create<moore::TanBIOp>(loc, value);
})
.Case("$exp",
[&]() -> Value {
return builder.create<moore::ExpBIOp>(loc, value);
})
.Case("$sqrt",
[&]() -> Value {
return builder.create<moore::SqrtBIOp>(loc, value);
})
.Case("$floor",
[&]() -> Value {
return builder.create<moore::FloorBIOp>(loc, value);
})
.Case("$ceil",
[&]() -> Value {
return builder.create<moore::CeilBIOp>(loc, value);
})
.Case("$asin",
[&]() -> Value {
return builder.create<moore::AsinBIOp>(loc, value);
})
.Case("$acos",
[&]() -> Value {
return builder.create<moore::AcosBIOp>(loc, value);
})
.Case("$atan",
[&]() -> Value {
return builder.create<moore::AtanBIOp>(loc, value);
})
.Case("$sinh",
[&]() -> Value {
return builder.create<moore::SinhBIOp>(loc, value);
})
.Case("$cosh",
[&]() -> Value {
return builder.create<moore::CoshBIOp>(loc, value);
})
.Case("$tanh",
[&]() -> Value {
return builder.create<moore::TanhBIOp>(loc, value);
})
.Case("$asinh",
[&]() -> Value {
return builder.create<moore::AsinhBIOp>(loc, value);
})
.Case("$acosh",
[&]() -> Value {
return builder.create<moore::AcoshBIOp>(loc, value);
})
.Case("$atanh",
[&]() -> Value {
return builder.create<moore::AtanhBIOp>(loc, value);
})
.Default([&]() -> Value { return {}; });
return systemCallRes();
}
5 changes: 5 additions & 0 deletions lib/Conversion/ImportVerilog/ImportVerilogInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,11 @@ struct Context {
moore::IntFormat defaultFormat = moore::IntFormat::Decimal,
bool appendNewline = false);

/// Convert system function calls only have arity-1.
FailureOr<Value>
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);

Expand Down
41 changes: 40 additions & 1 deletion test/Conversion/ImportVerilog/builtins.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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));
hailongSun2000 marked this conversation as resolved.
Show resolved Hide resolved
endfunction