Skip to content

Commit

Permalink
remove FixedPoint and Interval support (ucb-bar#624)
Browse files Browse the repository at this point in the history
Chisel5 removed both.
  • Loading branch information
ekiwi authored Mar 3, 2023
1 parent a6b1091 commit d8a44b2
Show file tree
Hide file tree
Showing 12 changed files with 6 additions and 845 deletions.
13 changes: 0 additions & 13 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,6 @@ scalacOptions ++= Seq(
"-Wconf:cat=deprecation&msg=Importing from firrtl is deprecated:s",
// do not warn about firrtl deprecations
"-Wconf:cat=deprecation&msg=will not be supported as part of the migration to the MLIR-based FIRRTL Compiler:s",
// TODO: remove FixedPoint support after 3.6 release
"-Wconf:cat=deprecation&msg=class FixedPoint:s",
"-Wconf:cat=deprecation&msg=class BinaryPoint:s",
"-Wconf:cat=deprecation&msg=object FixedPoint:s",
"-Wconf:cat=deprecation&msg=class fromDoubleToLiteral:s",
"-Wconf:cat=deprecation&msg=class fromBigDecimalToLiteral:s",
"-Wconf:cat=deprecation&msg=trait HasBinaryPoint:s",
"-Wconf:cat=deprecation&msg=object UnknownBinaryPoint:s",
// TODO: remove Interval support after 3.6 release
"-Wconf:cat=deprecation&msg=class Interval:s",
"-Wconf:cat=deprecation&msg=object Interval:s",
"-Wconf:cat=deprecation&msg=class fromBigDecimalToLiteralInterval:s",
"-Wconf:cat=deprecation&msg=class fromBigIntToLiteralInterval:s"
) ++ {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, n)) if n >= 13 => Seq("-Ymacro-annotations")
Expand Down
131 changes: 1 addition & 130 deletions src/main/scala/chiseltest/iotesters/PeekPokeTester.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package chiseltest.iotesters

import chisel3._
import chisel3.experimental.{FixedPoint, Interval}
import chisel3.internal.firrtl.KnownBinaryPoint
import chiseltest.simulator.SimulatorContext
import logger.LazyLogging

Expand Down Expand Up @@ -120,26 +118,6 @@ abstract class PeekPokeTester[T <: Module](val dut: T) extends LazyLogging {
case None => chisel3.internal.firrtl.UnknownWidth()
}

def pokeFixedPoint(signal: FixedPoint, value: Double): Unit = {
val bigInt = value.F(getFirrtlWidth(signal), signal.binaryPoint).litValue
poke(signal, bigInt)
}

def pokeFixedPointBig(signal: FixedPoint, value: BigDecimal): Unit = {
val bigInt = value.F(getFirrtlWidth(signal), signal.binaryPoint).litValue
poke(signal, bigInt)
}

def pokeInterval(signal: Interval, value: Double): Unit = {
val bigInt = value.I(getFirrtlWidth(signal), signal.binaryPoint).litValue
poke(signal, bigInt)
}

def pokeIntervalBig(signal: Interval, value: BigDecimal): Unit = {
val bigInt = value.I(getFirrtlWidth(signal), signal.binaryPoint).litValue
poke(signal, bigInt)
}

/** Locate a specific bundle element, given a name path.
* TODO: Handle Vecs
*
Expand Down Expand Up @@ -211,56 +189,14 @@ abstract class PeekPokeTester[T <: Module](val dut: T) extends LazyLogging {
def peek[E <: Element: Pokeable](signal: E): BigInt = {
if (!signal.isLit) {
val bits = backend.peek(fullSignalName(signal))
if (signal.isInstanceOf[SInt] || signal.isInstanceOf[Interval]) {
if (signal.isInstanceOf[SInt]) {
signExtend(bits, signal.widthOption.getOrElse(256))
} else {
bits
}
} else { signal.litValue }
}

/** Returns the value signal as a Double. Double may not be big enough to contain the
* value without precision loss. This situation will Throw ChiselException
* Consider using the more reliable [[peekFixedPointBig]]
*/
def peekFixedPoint(signal: FixedPoint): Double = {
val bigInt = peek(signal)
signal.binaryPoint match {
case KnownBinaryPoint(bp) => FixedPoint.toDouble(bigInt, bp)
case _ => throw new Exception("Cannot peekFixedPoint with unknown binary point location")
}
}

/** returns the value of signal as BigDecimal */
def peekFixedPointBig(signal: FixedPoint): BigDecimal = {
val bigInt = peek(signal)
signal.binaryPoint match {
case KnownBinaryPoint(bp) => FixedPoint.toBigDecimal(bigInt, bp)
case _ => throw new Exception("Cannot peekFixedPoint with unknown binary point location")
}
}

/** Returns the value signal as a Double. Double may not be big enough to contain the
* value without precision loss. This situation will Throw ChiselException
* Consider using the more reliable [[peekIntervalBig]]
*/
def peekInterval(signal: Interval): Double = {
val bigInt = peek(signal)
signal.binaryPoint match {
case KnownBinaryPoint(bp) => Interval.toDouble(bigInt, bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
}

/** returns the value of signal as BigDecimal */
def peekIntervalBig(signal: Interval): BigDecimal = {
val bigInt = peek(signal)
signal.binaryPoint match {
case KnownBinaryPoint(bp) => Interval.toBigDecimal(bigInt, bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
}

def peek(signal: Aggregate): Seq[BigInt] = {
extractElementBits(signal).map(x => backend.peek(fullSignalName(x)))
}
Expand Down Expand Up @@ -339,71 +275,6 @@ abstract class PeekPokeTester[T <: Module](val dut: T) extends LazyLogging {
expect(signal, BigInt(expected), msg)
}

/** Uses a Double as the expected value
*
* Consider using the more reliable [[expectFixedPointBig]]
*
* @param signal signal
* @param expected value expected
* @param msg message on failure
* @param epsilon error bounds on expected value are +/- epsilon
* @return
*/
def expectFixedPoint(signal: FixedPoint, expected: Double, msg: => String, epsilon: Double = 0.01): Boolean = {
val double = peekFixedPoint(signal)

expect((double - expected).abs < epsilon, msg)
}

/** Uses a BigDecimal as the expected value
*
* @param signal signal
* @param expected value expected
* @param msg message on failure
* @param epsilon error bounds on expected value are +/- epsilon
* @return
*/
def expectFixedPointBig(
signal: FixedPoint,
expected: BigDecimal,
msg: => String,
epsilon: BigDecimal = 0.01
): Boolean = {
val bigDecimal = peekFixedPointBig(signal)

expect((bigDecimal - expected).abs < epsilon, msg)
}

/** Uses a Double as the expected value
*
* Consider using the more reliable [[expectIntervalBig]]
*
* @param signal signal
* @param expected value expected
* @param msg message on failure
* @param epsilon error bounds on expected value are +/- epsilon
* @return
*/
def expectInterval(signal: Interval, expected: Double, msg: => String, epsilon: Double = 0.01): Boolean = {
val double = peekInterval(signal)

expect((double - expected).abs < epsilon, msg + s" expected: $expected; actual: $double")
}

/** Uses a BigDecimal as the expected value
*
* @param signal signal
* @param expected value expected
* @param msg message on failure
* @param epsilon error bounds on expected value are +/- epsilon
* @return
*/
def expectIntervalBig(signal: Interval, expected: BigDecimal, msg: => String, epsilon: BigDecimal = 0.01): Boolean = {
val bigDecimal = peekIntervalBig(signal)

expect((bigDecimal - expected).abs < epsilon, msg)
}

def expect(signal: Aggregate, expected: IndexedSeq[BigInt]): Boolean = {
extractElementBits(signal).zip(expected.reverse).forall { case (elem, value) =>
elem match {
Expand Down
130 changes: 4 additions & 126 deletions src/main/scala/chiseltest/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import scala.language.implicitConversions
import chiseltest.internal._
import chisel3._
import chisel3.experimental.{Direction, FixedPoint, Interval}
import chisel3.experimental.Direction
import chisel3.reflect.DataMirror
import chisel3.experimental.BundleLiterals._
import chisel3.experimental.VecLiterals._
Expand Down Expand Up @@ -106,109 +106,6 @@ package object chiseltest {
}
}

/** allows access to chisel Interval type signals with Scala native values */
implicit class testableInterval(x: Interval) {
private def asInterval(value: Double): Interval = value.I(Utils.getFirrtlWidth(x), x.binaryPoint)
private def asInterval(value: BigDecimal): Interval = value.I(Utils.getFirrtlWidth(x), x.binaryPoint)
def poke(value: Interval): Unit = {
require(x.binaryPoint == value.binaryPoint, "binary point mismatch")
Utils.pokeBits(x, value.litValue)
}
def poke(value: Double): Unit = poke(asInterval(value))
def poke(value: BigDecimal): Unit = poke(asInterval(value))
private[chiseltest] def expectInternal(value: Interval, message: Option[() => String]): Unit = {
require(x.binaryPoint == value.binaryPoint, "binary point mismatch")
// for backwards compatibility reasons, we do not support epsilon when expect is called with the Interval type.
Utils.expectBits(x, value.litValue, message, Some(Utils.fixedToString(x.binaryPoint)))
}
def expect(value: Interval): Unit = expectInternal(value, None)
def expect(value: Interval, message: => String): Unit = expectInternal(value, Some(() => message))
private[chiseltest] def expectInternal(expected: Double, epsilon: Double, userMsg: Option[() => String]): Unit = {
Utils.expectEpsilon(x, peekDouble(), expected, epsilon, userMsg)
}
def expect(value: Double): Unit = expectInternal(value, epsilon = 0.01, None)
def expect(value: Double, epsilon: Double): Unit = expectInternal(value, epsilon = epsilon, None)
def expect(value: Double, message: => String): Unit =
expectInternal(value, epsilon = 0.01, Some(() => message))
def expect(value: Double, message: => String, epsilon: Double): Unit =
expectInternal(value, epsilon = epsilon, Some(() => message))
private[chiseltest] def expectInternal(
expected: BigDecimal,
epsilon: BigDecimal,
userMsg: Option[() => String]
): Unit = {
Utils.expectEpsilon(x, peekBigDecimal(), expected, epsilon, userMsg)
}
def expect(value: BigDecimal): Unit = expectInternal(value, epsilon = 0.01, None)
def expect(value: BigDecimal, epsilon: BigDecimal): Unit = expectInternal(value, epsilon = epsilon, None)
def expect(value: BigDecimal, message: => String): Unit =
expectInternal(value, epsilon = 0.01, Some(() => message))
def expect(value: BigDecimal, message: => String, epsilon: BigDecimal): Unit =
expectInternal(value, epsilon = epsilon, Some(() => message))
def peek(): Interval = Context().backend.peekBits(x).I(x.binaryPoint)
def peekDouble(): Double = x.binaryPoint match {
case KnownBinaryPoint(bp) => Interval.toDouble(Context().backend.peekBits(x), bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
def peekBigDecimal(): BigDecimal = x.binaryPoint match {
case KnownBinaryPoint(bp) => Interval.toBigDecimal(Context().backend.peekBits(x), bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
}

/** allows access to chisel FixedPoint type signals with Scala native values */
implicit class testableFixedPoint(x: FixedPoint) {
private def asFixedPoint(value: Double): FixedPoint = value.F(Utils.getFirrtlWidth(x), x.binaryPoint)
private def asFixedPoint(value: BigDecimal): FixedPoint = value.F(Utils.getFirrtlWidth(x), x.binaryPoint)
def poke(value: FixedPoint): Unit = {
require(x.binaryPoint == value.binaryPoint, "binary point mismatch")
Utils.pokeBits(x, value.litValue)
}
def poke(value: Double): Unit = poke(asFixedPoint(value))
def poke(value: BigDecimal): Unit = poke(asFixedPoint(value))
private[chiseltest] def expectInternal(value: FixedPoint, message: Option[() => String]): Unit = {
require(x.binaryPoint == value.binaryPoint, "binary point mismatch")
// for backwards compatibility reasons, we do not support epsilon when expect is called with the FixedPoint type.
Utils.expectBits(x, value.litValue, message, Some(Utils.fixedToString(x.binaryPoint)))
}
def expect(value: FixedPoint): Unit = expectInternal(value, None)
def expect(value: FixedPoint, message: => String): Unit = expectInternal(value, Some(() => message))
private[chiseltest] def expectInternal(expected: Double, epsilon: Double, userMsg: Option[() => String]): Unit = {
Utils.expectEpsilon(x, peekDouble(), expected, epsilon, userMsg)
}
def expect(value: Double): Unit = expectInternal(value, epsilon = 0.01, None)
def expect(value: Double, epsilon: Double): Unit = expectInternal(value, epsilon = epsilon, None)
def expect(value: Double, message: => String): Unit =
expectInternal(value, epsilon = 0.01, Some(() => message))
def expect(value: Double, message: => String, epsilon: Double): Unit =
expectInternal(value, epsilon = epsilon, Some(() => message))
private[chiseltest] def expectInternal(
expected: BigDecimal,
epsilon: BigDecimal,
userMsg: Option[() => String]
): Unit = {
Utils.expectEpsilon(x, peekBigDecimal(), expected, epsilon, userMsg)
}
def expect(value: BigDecimal): Unit = expectInternal(value, epsilon = 0.01, None)
def expect(value: BigDecimal, epsilon: BigDecimal): Unit = expectInternal(value, epsilon = epsilon, None)
def expect(value: BigDecimal, message: => String): Unit =
expectInternal(value, epsilon = 0.01, Some(() => message))
def expect(value: BigDecimal, message: => String, epsilon: BigDecimal): Unit =
expectInternal(value, epsilon = epsilon, Some(() => message))
def peek(): FixedPoint = {
val multiplier = BigDecimal(2).pow(x.binaryPoint.get)
(BigDecimal(Context().backend.peekBits(x)) / multiplier).F(x.binaryPoint)
}
def peekDouble(): Double = x.binaryPoint match {
case KnownBinaryPoint(bp) => FixedPoint.toDouble(Context().backend.peekBits(x), bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
def peekBigDecimal(): BigDecimal = x.binaryPoint match {
case KnownBinaryPoint(bp) => FixedPoint.toBigDecimal(Context().backend.peekBits(x), bp)
case _ => throw new Exception("Cannot peekInterval with unknown binary point location")
}
}

implicit class testableRecord[T <: Record](x: T) {

/** Poke the given signal with a [[Record.litValue()]]
Expand Down Expand Up @@ -289,8 +186,6 @@ package object chiseltest {
case (x: Bool, value: Bool) => x.poke(value)
case (x: UInt, value: UInt) => x.poke(value)
case (x: SInt, value: SInt) => x.poke(value)
case (x: FixedPoint, value: FixedPoint) => x.poke(value)
case (x: Interval, value: Interval) => x.poke(value)
case (x: Record, value: Record) =>
require(DataMirror.checkTypeEquivalence(x, value), s"Record type mismatch")
x.elements.zip(value.elements).foreach { case ((_, x), (_, value)) =>
Expand All @@ -310,11 +205,9 @@ package object chiseltest {
}

def peek(): T = x match {
case x: Bool => x.peek().asInstanceOf[T]
case x: UInt => x.peek().asInstanceOf[T]
case x: SInt => x.peek().asInstanceOf[T]
case x: FixedPoint => x.peek().asInstanceOf[T]
case x: Interval => x.peek().asInstanceOf[T]
case x: Bool => x.peek().asInstanceOf[T]
case x: UInt => x.peek().asInstanceOf[T]
case x: SInt => x.peek().asInstanceOf[T]
case x: Record =>
val elementValueFns = x.elements.map { case (name: String, elt: Data) =>
(y: Record) => (y.elements(name), elt.peek())
Expand All @@ -335,8 +228,6 @@ package object chiseltest {
case (x: Bool, value: Bool) => x.expectInternal(value.litValue, message)
case (x: UInt, value: UInt) => x.expectInternal(value.litValue, message)
case (x: SInt, value: SInt) => x.expectInternal(value.litValue, message)
case (x: FixedPoint, value: FixedPoint) => x.expectInternal(value, message)
case (x: Interval, value: Interval) => x.expectInternal(value, message)
case (x: Record, value: Record) =>
require(DataMirror.checkTypeEquivalence(x, value), s"Record type mismatch")
x.elements.zip(value.elements).foreach { case ((_, x), (_, value)) =>
Expand Down Expand Up @@ -429,19 +320,6 @@ package object chiseltest {

def boolBitsToString(bits: BigInt): String = (bits != 0).toString

def fixedToString(binaryPoint: BinaryPoint): BigInt => String = {
def inner(bits: BigInt): String = {
binaryPoint match {
case KnownBinaryPoint(binaryPoint) =>
val bpInteger = 1 << binaryPoint
(bits.toFloat / bpInteger).toString
case UnknownBinaryPoint => "[unknown binary point]"
}
}

inner
}

def enumToString(tpe: EnumType): BigInt => String = {
def inner(bits: BigInt): String = {
val fullName = chisel3.internaltest.EnumHelpers.valueToName(tpe, bits).getOrElse("???")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class HasOddWidthSInt extends Module {
out := masked === in
}

// The poke of a negative number into an SInt, FixedPoint, or Interval input that is not a standard word size
// The poke of a negative number into an SInt input that is not a standard word size
// would break in verilator if the poked value was not masked to the correct number of
// bits first. This was fixed by masking those values to the proper width before poking
class NegativeInputValuesTest extends AnyFreeSpec with ChiselScalatestTester {
Expand Down
Loading

0 comments on commit d8a44b2

Please sign in to comment.