Skip to content

Commit

Permalink
Clean up API and add tests that use chiseltest.iotesters
Browse files Browse the repository at this point in the history
* Update fixedpoint library
  • Loading branch information
konda-x1 authored and milovanovic committed Aug 18, 2023
1 parent 2fa039f commit be239b9
Show file tree
Hide file tree
Showing 25 changed files with 2,513 additions and 67 deletions.
82 changes: 41 additions & 41 deletions src/main/scala/dsptools/numbers/chisel_concrete/DspReal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,41 +77,41 @@ class DspReal() extends Bundle {
twoOperandBool(arg1, Module(new BBFNotEquals()))
}

def ln(dummy: Int = 0): DspReal = {
def ln: DspReal = {
oneOperandOperator(Module(new BBFLn()))
}

def log10(dummy: Int = 0): DspReal = {
def log10: DspReal = {
oneOperandOperator(Module(new BBFLog10()))
}

def exp(dummy: Int = 0): DspReal = {
def exp: DspReal = {
oneOperandOperator(Module(new BBFExp()))
}

def sqrt(dummy: Int = 0): DspReal = {
def sqrt: DspReal = {
oneOperandOperator(Module(new BBFSqrt()))
}

def pow(arg1: DspReal): DspReal = {
twoOperandOperator(arg1, Module(new BBFPow()))
}

def floor(dummy: Int = 0): DspReal = {
def floor: DspReal = {
oneOperandOperator(Module(new BBFFloor()))
}

def ceil(dummy: Int = 0): DspReal = {
def ceil: DspReal = {
oneOperandOperator(Module(new BBFCeil()))
}

def round(): DspReal = (this + DspReal(0.5)).floor()
def round: DspReal = (this + DspReal(0.5)).floor

def truncate(): DspReal = {
Mux(this < DspReal(0.0), this.ceil(), this.floor())
def truncate: DspReal = {
Mux(this < DspReal(0.0), this.ceil, this.floor)
}

def abs(): DspReal = Mux(this < DspReal(0.0), DspReal(0.0) - this, this)
def abs: DspReal = Mux(this < DspReal(0.0), DspReal(0.0) - this, this)

// Assumes you're using chisel testers
private def backendIsVerilator: Boolean = true
Expand All @@ -131,7 +131,7 @@ class DspReal() extends Bundle {
// Swept in increments of 0.0001pi, and got ~11 decimal digits of accuracy
// Can add more half angle recursion for more precision
//scalastyle:off magic.number
def sin(dummy: Int = 0): DspReal = {
def sin: DspReal = {
if (backendIsVerilator) {
// Taylor series; Works best close to 0 (-pi/2, pi/2) -- so normalize!
def sinPiOver2(in: DspReal): DspReal = {
Expand All @@ -143,7 +143,7 @@ class DspReal() extends Bundle {
val terms = TrigUtility.sinCoeff(nmax).zip(xpow).map { case ((c, scale), x) => DspReal(c) * x / DspReal(scale) }
terms.reduceRight(_ + _) * in
}
val num2Pi = (this / twoPi).truncate()
val num2Pi = (this / twoPi).truncate
// Repeats every 2*pi, so normalize to -pi, pi
val normalized2Pi = this - num2Pi * twoPi
val temp1 = Mux(normalized2Pi > pi, normalized2Pi - twoPi, normalized2Pi)
Expand Down Expand Up @@ -182,19 +182,19 @@ class DspReal() extends Bundle {
}
}

def cos(dummy: Int = 0): DspReal = {
if (backendIsVerilator) (this + halfPi).sin()
def cos: DspReal = {
if (backendIsVerilator) (this + halfPi).sin
else oneOperandOperator(Module(new BBFCos()))
}

// Swept input at 0.0001pi increments. For tan < 1e9, ~8 decimal digit precision (fractional)
// WARNING: tan blows up (more likely to be wrong when abs is close to pi/2)
def tan(dummy: Int = 0): DspReal = {
def tan: DspReal = {
if (backendIsVerilator) {
def tanPiOver2(in: DspReal): DspReal = {
in.sin() / in.cos()
in.sin / in.cos
}
val numPi = (this / pi).truncate()
val numPi = (this / pi).truncate
// Repeats every pi, so normalize to -pi/2, pi/2
// tan(x + pi) = tan(x)
val normalizedPi = this - numPi * pi
Expand All @@ -208,7 +208,7 @@ class DspReal() extends Bundle {

// Correct to 9 decimal digits sweeping by 0.0001pi
// See http://myweb.lmu.edu/hmedina/papers/reprintmonthly156-161-medina.pdf
def atan(dummy: Int = 0): DspReal = {
def atan: DspReal = {
if (backendIsVerilator) {
def arctanPiOver2(in: DspReal): DspReal = {
val m = TrigUtility.atanM
Expand All @@ -223,7 +223,7 @@ class DspReal() extends Bundle {
}
val isNeg = this.signBit
// arctan(-x) = -arctan(x)
val inTemp = this.abs()
val inTemp = this.abs
// arctan(x) = pi/2 - arctan(1/x) for x > 0
// Approximation accuracy in [0, 1]
val outTemp = Mux(inTemp > one, halfPi - arctanPiOver2(one / inTemp), arctanPiOver2(inTemp))
Expand All @@ -234,18 +234,18 @@ class DspReal() extends Bundle {
// See https://en.wikipedia.org/wiki/Inverse_trigonometric_functions

// Must be -1 <= x <= 1
def asin(dummy: Int = 0): DspReal = {
def asin: DspReal = {
if (backendIsVerilator) {
val sqrtIn = one - (this * this)
val atanIn = this / (one + sqrtIn.sqrt())
DspReal(2) * atanIn.atan()
val atanIn = this / (one + sqrtIn.sqrt)
DspReal(2) * atanIn.atan
} else oneOperandOperator(Module(new BBFASin()))
}

// Must be -1 <= x <= 1
def acos(dummy: Int = 0): DspReal = {
def acos: DspReal = {
if (backendIsVerilator) {
halfPi - this.asin()
halfPi - this.asin
} else oneOperandOperator(Module(new BBFACos()))
}

Expand All @@ -256,7 +256,7 @@ class DspReal() extends Bundle {
val x = arg1
val y = this
val atanArg = y / x
val atanRes = atanArg.atan()
val atanRes = atanArg.atan
val muxIn: Iterable[(Bool, DspReal)] = Iterable(
(x > zero) -> atanRes,
(x.signBit && !y.signBit) -> (atanRes + pi),
Expand All @@ -270,57 +270,57 @@ class DspReal() extends Bundle {
}

def hypot(arg1: DspReal): DspReal = {
if (backendIsVerilator) (this * this + arg1 * arg1).sqrt()
if (backendIsVerilator) (this * this + arg1 * arg1).sqrt
else twoOperandOperator(arg1, Module(new BBFHypot()))
}

// See https://en.wikipedia.org/wiki/Hyperbolic_function

def sinh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) (this.exp() - (zero - this).exp()) / DspReal(2)
def sinh: DspReal = {
if (backendIsVerilator) (this.exp - (zero - this).exp) / DspReal(2)
else oneOperandOperator(Module(new BBFSinh()))
}

def cosh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) (this.exp() + (zero - this).exp()) / DspReal(2)
def cosh: DspReal = {
if (backendIsVerilator) (this.exp + (zero - this).exp) / DspReal(2)
else oneOperandOperator(Module(new BBFCosh()))
}

def tanh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) (this.exp() - (zero - this).exp()) / (this.exp() + (zero - this).exp())
def tanh: DspReal = {
if (backendIsVerilator) (this.exp - (zero - this).exp) / (this.exp + (zero - this).exp)
else oneOperandOperator(Module(new BBFTanh()))
}

// Requires Breeze for testing:

def asinh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) ((this * this + one).sqrt() + this).ln()
def asinh: DspReal = {
if (backendIsVerilator) ((this * this + one).sqrt + this).ln
else oneOperandOperator(Module(new BBFASinh()))
}

// x >= 1
def acosh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) ((this * this - one).sqrt() + this).ln()
def acosh: DspReal = {
if (backendIsVerilator) ((this * this - one).sqrt + this).ln
else oneOperandOperator(Module(new BBFACosh()))
}

// |x| < 1
def atanh(dummy: Int = 0): DspReal = {
if (backendIsVerilator) ((one + this) / (one - this)).ln() / DspReal(2)
def atanh: DspReal = {
if (backendIsVerilator) ((one + this) / (one - this)).ln / DspReal(2)
else oneOperandOperator(Module(new BBFATanh()))
}

// Not used directly -- there's an equivalent in the type classes (was causing some confusion)
/*
def intPart(dummy: Int = 0): DspReal = {
def intPart: DspReal = {
oneOperandOperator(Module(new BBFIntPart()))
}
*/

/** Returns this Real's value rounded to a signed integer.
* Behavior on overflow (possible with large exponent terms) is undefined.
*/
def toSInt(dummy: Int = 0): SInt = {
def toSInt: SInt = {
println(Console.YELLOW + "WARNING: Real -> SInt === THIS DESIGN IS NOT SYNTHESIZABLE!" + Console.RESET)
val blackbox = Module(new BBFToInt)
blackbox.io.in := node
Expand All @@ -330,7 +330,7 @@ class DspReal() extends Bundle {

/** Returns this Real's value as its bit representation in DspReal.underlyingWidth-bit floating point.
*/
def toDoubleBits(dummy: Int = 0): UInt = {
def toDoubleBits: UInt = {
node
}
}
Expand Down
32 changes: 16 additions & 16 deletions src/main/scala/dsptools/numbers/chisel_concrete/RealTrig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ package dsptools.numbers

// Make using these ops more like using math.opName
object RealTrig {
def ln(x: DspReal) = x.ln()
def log10(x: DspReal) = x.log10()
def exp(x: DspReal) = x.exp()
def sqrt(x: DspReal) = x.sqrt()
def ln(x: DspReal) = x.ln
def log10(x: DspReal) = x.log10
def exp(x: DspReal) = x.exp
def sqrt(x: DspReal) = x.sqrt
def pow(x: DspReal, n: DspReal) = x.pow(n)
def sin(x: DspReal) = x.sin()
def cos(x: DspReal) = x.cos()
def tan(x: DspReal) = x.tan()
def atan(x: DspReal) = x.atan()
def asin(x: DspReal) = x.asin()
def acos(x: DspReal) = x.acos()
def sin(x: DspReal) = x.sin
def cos(x: DspReal) = x.cos
def tan(x: DspReal) = x.tan
def atan(x: DspReal) = x.atan
def asin(x: DspReal) = x.asin
def acos(x: DspReal) = x.acos
def atan2(y: DspReal, x: DspReal) = y.atan2(x)
def hypot(x: DspReal, y: DspReal) = x.hypot(y)
def sinh(x: DspReal) = x.sinh()
def cosh(x: DspReal) = x.cosh()
def tanh(x: DspReal) = x.tanh()
def asinh(x: DspReal) = x.asinh()
def acosh(x: DspReal) = x.acosh()
def atanh(x: DspReal) = x.tanh()
def sinh(x: DspReal) = x.sinh
def cosh(x: DspReal) = x.cosh
def tanh(x: DspReal) = x.tanh
def asinh(x: DspReal) = x.asinh
def acosh(x: DspReal) = x.acosh
def atanh(x: DspReal) = x.tanh
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ trait DspRealSigned extends Any with Signed[DspReal] with DspRealRing with hasCo
def signum(a: DspReal): ComparisonBundle = {
ComparisonHelper(a === DspReal(0.0), a < DspReal(0.0))
}
def abs(a: DspReal): DspReal = a.abs()
def abs(a: DspReal): DspReal = a.abs
def context_abs(a: DspReal): DspReal = {
Mux(
isSignNonNegative(ShiftRegister(a, context.numAddPipes)),
Expand All @@ -61,16 +61,16 @@ trait DspRealSigned extends Any with Signed[DspReal] with DspRealRing with hasCo

trait DspRealIsReal extends Any with IsReal[DspReal] with DspRealOrder with DspRealSigned with hasContext {
def ceil(a: DspReal): DspReal = {
a.ceil()
a.ceil
}
def context_ceil(a: DspReal): DspReal = {
ShiftRegister(a, context.numAddPipes).ceil()
ShiftRegister(a, context.numAddPipes).ceil
}
def floor(a: DspReal): DspReal = a.floor()
def floor(a: DspReal): DspReal = a.floor
def isWhole(a: DspReal): Bool = a === round(a)
// Round *half up* -- Different from System Verilog definition! (where half is rounded away from zero)
// according to 5.7.2 (http://www.ece.uah.edu/~gaede/cpe526/2012%20System%20Verilog%20Language%20Reference%20Manual.pdf)
def round(a: DspReal): DspReal = a.round()
def round(a: DspReal): DspReal = a.round
def truncate(a: DspReal): DspReal = {
Mux(
ShiftRegister(a, context.numAddPipes) < DspReal(0.0),
Expand Down Expand Up @@ -136,7 +136,7 @@ trait DspRealReal
def signBit(a: DspReal): Bool = isSignNegative(a)
override def fromInt(n: Int): DspReal = super[ConvertableToDspReal].fromInt(n)
override def fromBigInt(n: BigInt): DspReal = super[ConvertableToDspReal].fromBigInt(n)
def intPart(a: DspReal): SInt = truncate(a).toSInt()
def intPart(a: DspReal): SInt = truncate(a).toSInt
// WARNING: Beware of overflow(!)
def asFixed(a: DspReal, proto: FixedPoint): FixedPoint = {
require(proto.binaryPoint.known, "Binary point must be known for DspReal -> FixedPoint")
Expand All @@ -145,7 +145,7 @@ trait DspRealReal
val out = Wire(proto.cloneType)
out := DspContext.withTrimType(NoTrim) {
// round is round half up
round(a * DspReal((1 << bp).toDouble)).toSInt().asFixed.div2(bp)
round(a * DspReal((1 << bp).toDouble)).toSInt.asFixed.div2(bp)
}
out
}
Expand Down
Loading

0 comments on commit be239b9

Please sign in to comment.