Skip to content
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
46 changes: 46 additions & 0 deletions integration_tests/MATH_INTRINSICS/math_intrinsics.va
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
`include "constants.vams"
`include "disciplines.vams"

// Exercises every math builtin that `Builder::intrinsic` routes to an LLVM
// intrinsic or a libm symbol. Most of them were called by no other model in
// the suite, so a missing or mis-declared entry in `CodegenCx::intrinsic`
// stayed invisible until a user hit it: `ceil` aborted codegen outright and
// `hypot` emitted a module that failed the LLVM verifier.
//
// Every argument is derived from a branch voltage, otherwise constant folding
// would evaluate the call before it ever reaches codegen and the coverage
// would be lost.
module math_intrinsics(A, C);
inout A, C;
electrical A, C;

branch (A, C) br;

(*desc = "Output scale", units = "A/V"*) parameter real scale = 1.0 from (0:inf);

real x, unit, upper, acc;
integer ix;

analog begin
x = V(br);

// |unit| < 1 keeps asin/acos/atanh inside their domain
unit = x / sqrt(1.0 + x * x);
// upper >= 1 keeps ln/log/acosh inside theirs
upper = 1.0 + x * x;

acc = sqrt(upper) + exp(-upper) + ln(upper) + log(upper);
acc = acc + floor(x) + ceil(x);
acc = acc + sin(x) + cos(x) + tan(unit);
acc = acc + asin(unit) + acos(unit) + atan(x);
acc = acc + sinh(unit) + cosh(unit) + tanh(x);
acc = acc + asinh(x) + acosh(upper) + atanh(unit);
acc = acc + hypot(x, 1.0) + atan2(x, 1.0) + pow(upper, unit);

// real -> integer cast and $clog2 also resolve through the intrinsic path
ix = upper * 8.0;
acc = acc + $clog2(ix);

I(br) <+ scale * acc;
end
endmodule
4 changes: 2 additions & 2 deletions openvaf/hir_ty/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ bultins! {
const fn REAL_INFO() -> Real;
const fn REAL_MATH_1(Val(Real)) -> Real;
const fn REAL_MATH_2(Val(Real),Val(Real)) -> Real;
const fn INT_MATH_2(Val(Integer),Val(Integer)) -> Integer;
const fn INT_MATH_1(Val(Integer)) -> Integer;


VT = const {
Expand Down Expand Up @@ -431,7 +431,7 @@ copied_builtins! {
FLOOR = REAL_MATH_1
LN = REAL_MATH_1
LOG = REAL_MATH_1
CLOG2 = INT_MATH_2
CLOG2 = INT_MATH_1
LOG10 = REAL_MATH_1
CEIL = REAL_MATH_1
LIMEXP = REAL_MATH_1
Expand Down
3 changes: 2 additions & 1 deletion openvaf/mir_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,8 @@ impl<'ll> Builder<'_, '_, 'll> {
Opcode::Log => NonNull::from(self.intrinsic(args, "llvm.log10.f64")).as_ptr(),
Opcode::Clog2 => {
let leading_zeros =
NonNull::from(self.intrinsic(&[args[0], true.into()], "llvm.ctlz")).as_ptr();
NonNull::from(self.intrinsic(&[args[0], true.into()], "llvm.ctlz.i32"))
.as_ptr();
let total_bits = NonNull::from(self.cx.const_int(32)).as_ptr();
llvm_sys::core::LLVMBuildSub(self.llbuilder, total_bits, leading_zeros, UNNAMED)
}
Expand Down
5 changes: 3 additions & 2 deletions openvaf/mir_llvm/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ impl<'a, 'll> CodegenCx<'a, 'll> {
ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
ifn!("llvm.ctlz", fn(t_i32, t_bool) -> t_i32);
ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
ifn!("llvm.ctlz.i32", fn(t_i32, t_bool) -> t_i32);

// not technically intrinsics but part of the C standard library
// TODO link custom mathematical functions
Expand All @@ -56,7 +57,7 @@ impl<'a, 'll> CodegenCx<'a, 'll> {

if name == "hypot" {
let name = if self.target.options.is_like_windows { "_hypot" } else { "hypot" };
return Some(self.insert_intrinsic(name, &[t_f64], t_f64, false));
return Some(self.insert_intrinsic(name, &[t_f64, t_f64], t_f64, false));
}

ifn!("strcmp", fn(t_str, t_str) -> t_i32);
Expand Down
14 changes: 14 additions & 0 deletions openvaf/test_data/osdi/math_intrinsics.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
param "$mfactor"
units = "", desc = "Multiplier (Verilog-A $mfactor)", flags = ParameterFlags(PARA_KIND_INST)
param "scale"
units = "A/V", desc = "Output scale", flags = ParameterFlags(0x0)

2 terminals
node "A" units = "V", runits = "A"
node "C" units = "V", runits = "A"
jacobian (A, A) JacobianFlags(JACOBIAN_ENTRY_RESIST | JACOBIAN_ENTRY_REACT_CONST)
jacobian (A, C) JacobianFlags(JACOBIAN_ENTRY_RESIST | JACOBIAN_ENTRY_REACT_CONST)
jacobian (C, A) JacobianFlags(JACOBIAN_ENTRY_RESIST | JACOBIAN_ENTRY_REACT_CONST)
jacobian (C, C) JacobianFlags(JACOBIAN_ENTRY_RESIST | JACOBIAN_ENTRY_REACT_CONST)
0 states
has bound_step false