pascalkuthe / OpenVAF

An innovative Verilog-A compiler
https://openvaf.semimod.de/
GNU General Public License v3.0
116 stars 16 forks source link

issue with node collapse for non-zero potential contribution #138

Open gjcoram opened 2 weeks ago

gjcoram commented 2 weeks ago

The module contrib2 (rename attachment contrib2.txt to contrib2.sp) acts like a 0V voltage source in ngspice-42, even though the contribution is 1.0:

V(out,in) <+ 1.0;

Curiously, if I change the contribution to an integer:

V(out,in) <+ 1;

as in contrib3.txt, then it works properly.

contrib2.txt contrib3.txt

gjcoram commented 2 weeks ago

I found that ngspice gets told that the internal node (branch current for the voltage source) can be collapsed. When I dug further in to OpenVAF, I came across the is_zero() function for Literal (in hir_def/src/expr.rs). contrib3 matches Literal::Int(0) => true, whereas contrib2 matches Literal::Float(val) => val.is_zero(), and, for some reason, val.is_zero() returns true, even though the value is 1.0, which should be non-zero.

If I change that line to Literal::Float(val) => *val == Ieee64::with_float(0.0), then contrib2 works properly.

gjcoram commented 2 weeks ago

From lib/stdx/src/ieee64.rs: /// Get the bitwise representation. pub fn is_zero(self) -> bool { // IEEE number is zero if mantissa is zero (self.0 & 0x000FFFFFFFFFFFFF) == 0 }

gjcoram commented 2 weeks ago

The problem appears to be that 1.0 has a special IEEE 754 representation, see https://en.wikipedia.org/wiki/IEEE_754-1985#Examples 1.0 is represented by a fractional part that is all zeros, but the exponent is 0111 1111