diff options
| author | Chick Markley | 2019-10-18 19:44:08 -0700 |
|---|---|---|
| committer | Adam Izraelevitz | 2019-10-18 19:44:08 -0700 |
| commit | 7b93b0f8c48e39cc9730cf9f91340cf733dadafe (patch) | |
| tree | 3e9666c29d6c9901f221fed4728d05b9fd75067e /chiselFrontend/src/main/scala/chisel3/internal | |
| parent | fafd984a923591841917cd4c3a1f4c823dc485b4 (diff) | |
Interval Data Type Support for Chisel (#1210)
Plan to be released with 3.3.
Breaks experimental Range API.
Adds new Interval type and associated support.
This commit adds the following:
- Renamed Range to IntervalRange to avoid name collision with scala Range
- Changed RangeTransform macro to Return an IntervalRange
- Improved error messages on missing comma or decimal
- Added notational support for binary point
- Some formatting cleanup also
- SIntFactory
- Change to use IntervalRange API
- UIntFactory
- UInt from range has custom width computation
- It does not need to deal with lowerbound extending bit requirements
- Code to handle special case of range"[0,0]" to have a width of 1
- IR.scala
- Removed Bound and other constraint code that was duplicating firrtl stuff
- Added new RangeType
- Added IntervalRange class and object
- RangeSpec
- modified just a bit to handle notational differences
- previous range interpolator returned tuple now returns IntervalRange
- Add IntervalType to emitter
- Added IntervalSpec with many tests
- Added ScalaIntervalSimulatorSpec which tests golden model for Interval
- Added ScalaIntervalSimulator which is a golden model for Interval
- This gold may not have been polished to a high sheen
- Add IntervalLit cases to Converter
- Add Interval PrimOps to IR
- asInterval, wrap, squz, clip, setp, decp, incp
- Add IntervalLit class to IR
- Add Interval to MonoConnect
- Add Interval Type to Bits (in experimental package)
- add conversions to Interval from other types
- Add Interval clone stuff to Data
- Add Literal creation helpers to chisel3 package
- these may move to experimental if I can figure that out
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/internal')
3 files changed, 509 insertions, 52 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala index 1c001183..41402021 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala @@ -3,7 +3,7 @@ package chisel3.internal import chisel3._ -import chisel3.experimental.{Analog, BaseModule, EnumType, FixedPoint, UnsafeEnum} +import chisel3.experimental.{Analog, BaseModule, EnumType, FixedPoint, Interval, UnsafeEnum} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} import scala.language.experimental.macros @@ -85,6 +85,8 @@ private[chisel3] object MonoConnect { elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: FixedPoint, source_e: FixedPoint) => elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) + case (sink_e: Interval, source_e: Interval) => + elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: Clock, source_e: Clock) => elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod) case (sink_e: AsyncReset, source_e: AsyncReset) => diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala index 5309609b..548ed294 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -71,6 +71,11 @@ private[chisel3] object Converter { val uint = convert(ULit(unsigned, fplit.width), ctx) val lit = bp.asInstanceOf[KnownBinaryPoint].value fir.DoPrim(firrtl.PrimOps.AsFixedPoint, Seq(uint), Seq(lit), fir.UnknownType) + case intervalLit @ IntervalLit(n, w, bp) => + val unsigned = if (n < 0) (BigInt(1) << intervalLit.width.get) + n else n + val uint = convert(ULit(unsigned, intervalLit.width), ctx) + val lit = bp.asInstanceOf[KnownBinaryPoint].value + fir.DoPrim(firrtl.PrimOps.AsInterval, Seq(uint), Seq(n, n, lit), fir.UnknownType) case lit: ILit => throwException(s"Internal Error! Unexpected ILit: $lit") } @@ -220,6 +225,7 @@ private[chisel3] object Converter { case d: UInt => fir.UIntType(convert(d.width)) case d: SInt => fir.SIntType(convert(d.width)) case d: FixedPoint => fir.FixedType(convert(d.width), convert(d.binaryPoint)) + case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) case d: Analog => fir.AnalogType(convert(d.width)) case d: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir), d.length) case d: Record => diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 4643f66c..bc662ddb 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -5,11 +5,15 @@ package chisel3.internal.firrtl import chisel3._ import chisel3.internal._ import chisel3.internal.sourceinfo.SourceInfo -import chisel3.experimental.{BaseModule, ChiselAnnotation, Param} +import chisel3.experimental._ +import _root_.firrtl.{ir => firrtlir} +import _root_.firrtl.PrimOps + +import scala.math.BigDecimal.RoundingMode // scalastyle:off number.of.types -case class PrimOp(val name: String) { +case class PrimOp(name: String) { override def toString: String = name } @@ -45,7 +49,13 @@ object PrimOp { val AsUIntOp = PrimOp("asUInt") val AsSIntOp = PrimOp("asSInt") val AsFixedPointOp = PrimOp("asFixedPoint") - val SetBinaryPoint = PrimOp("bpset") + val AsIntervalOp = PrimOp("asInterval") + val WrapOp = PrimOp("wrap") + val SqueezeOp = PrimOp("squz") + val ClipOp = PrimOp("clip") + val SetBinaryPoint = PrimOp("setp") + val IncreasePrecision = PrimOp("incp") + val DecreasePrecision = PrimOp("decp") val AsClockOp = PrimOp("asClock") val AsAsyncResetOp = PrimOp("asAsyncReset") } @@ -111,6 +121,18 @@ case class FPLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends LitArg(n def minWidth: Int = 1 + n.bitLength } +case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends LitArg(n, w) { + def name: String = { + val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n + s"asInterval(${ULit(unsigned, width).name}, ${n}, ${n}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})" + } + val range: IntervalRange = { + new IntervalRange(IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getBound(isClosed = true, BigDecimal(n)), IntervalRange.getRangeWidth(binaryPoint)) + } + def minWidth: Int = 1 + n.bitLength +} + case class Ref(name: String) extends Arg case class ModuleIO(mod: BaseModule, name: String) extends Arg { override def fullName(ctx: Component): String = @@ -125,54 +147,6 @@ case class Index(imm: Arg, value: Arg) extends Arg { override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" } -sealed trait Bound -sealed trait NumericBound[T] extends Bound { - val value: T -} -sealed case class Open[T](value: T) extends NumericBound[T] -sealed case class Closed[T](value: T) extends NumericBound[T] - -sealed trait Range { - val min: Bound - val max: Bound - def getWidth: Width -} - -sealed trait KnownIntRange extends Range { - val min: NumericBound[Int] - val max: NumericBound[Int] - - require( (min, max) match { - case (Open(low_val), Open(high_val)) => low_val < high_val - 1 - case (Closed(low_val), Open(high_val)) => low_val < high_val - case (Open(low_val), Closed(high_val)) => low_val < high_val - case (Closed(low_val), Closed(high_val)) => low_val <= high_val - }) -} - -sealed case class KnownUIntRange(min: NumericBound[Int], max: NumericBound[Int]) extends KnownIntRange { - require (min.value >= 0) - - def getWidth: Width = max match { - case Open(v) => Width(BigInt(v - 1).bitLength.max(1)) - case Closed(v) => Width(BigInt(v).bitLength.max(1)) - } -} - -sealed case class KnownSIntRange(min: NumericBound[Int], max: NumericBound[Int]) extends KnownIntRange { - - val maxWidth = max match { - case Open(v) => Width(BigInt(v - 1).bitLength + 1) - case Closed(v) => Width(BigInt(v).bitLength + 1) - } - val minWidth = min match { - case Open(v) => Width(BigInt(v + 1).bitLength + 1) - case Closed(v) => Width(BigInt(v).bitLength + 1) - } - def getWidth: Width = maxWidth.max(minWidth) - -} - object Width { def apply(x: Int): Width = KnownWidth(x) def apply(): Width = UnknownWidth() @@ -257,6 +231,481 @@ object MemPortDirection { object INFER extends MemPortDirection("infer") } +sealed trait RangeType { + def getWidth: Width + + def * (that: IntervalRange): IntervalRange + def +& (that: IntervalRange): IntervalRange + def -& (that: IntervalRange): IntervalRange + def << (that: Int): IntervalRange + def >> (that: Int): IntervalRange + def << (that: KnownWidth): IntervalRange + def >> (that: KnownWidth): IntervalRange + def merge(that: IntervalRange): IntervalRange +} + +object IntervalRange { + /** Creates an IntervalRange, this is used primarily by the range interpolator macro + * @param lower lower bound + * @param upper upper bound + * @param firrtlBinaryPoint binary point firrtl style + * @return + */ + def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, firrtlBinaryPoint: firrtlir.Width): IntervalRange = { + new IntervalRange(lower, upper, firrtlBinaryPoint) + } + + def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, binaryPoint: BinaryPoint): IntervalRange = { + new IntervalRange(lower, upper, IntervalRange.getBinaryPoint(binaryPoint)) + } + + def apply(lower: firrtlir.Bound, upper: firrtlir.Bound, binaryPoint: Int): IntervalRange = { + IntervalRange(lower, upper, BinaryPoint(binaryPoint)) + } + + /** Returns an IntervalRange appropriate for a signed value of the given width + * @param binaryPoint number of bits of mantissa + * @return + */ + def apply(binaryPoint: BinaryPoint): IntervalRange = { + IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint) + } + + /** Returns an IntervalRange appropriate for a signed value of the given width + * @param width number of bits to have in the interval + * @param binaryPoint number of bits of mantissa + * @return + */ + def apply(width: Width, binaryPoint: BinaryPoint = 0.BP): IntervalRange = { + val range = width match { + case KnownWidth(w) => + val nearestPowerOf2 = BigInt("1" + ("0" * (w - 1)), 2) + IntervalRange( + firrtlir.Closed(BigDecimal(-nearestPowerOf2)), firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), binaryPoint + ) + case _ => + IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint) + } + range + } + + def unapply(arg: IntervalRange): Option[(firrtlir.Bound, firrtlir.Bound, BinaryPoint)] = { + return Some((arg.lower, arg.upper, arg.binaryPoint)) + } + + def getBound(isClosed: Boolean, value: String): firrtlir.Bound = { + if(value == "?") { + firrtlir.UnknownBound + } + else if(isClosed) { + firrtlir.Closed(BigDecimal(value)) + } + else { + firrtlir.Open(BigDecimal(value)) + } + } + + def getBound(isClosed: Boolean, value: BigDecimal): firrtlir.Bound = { + if(isClosed) { + firrtlir.Closed(value) + } + else { + firrtlir.Open(value) + } + } + + def getBound(isClosed: Boolean, value: Int): firrtlir.Bound = { + getBound(isClosed, (BigDecimal(value))) + } + + def getBinaryPoint(s: String): firrtlir.Width = { + firrtlir.UnknownWidth + } + + def getBinaryPoint(n: Int): firrtlir.Width = { + if(n < 0) { + firrtlir.UnknownWidth + } + else { + firrtlir.IntWidth(n) + } + } + def getBinaryPoint(n: BinaryPoint): firrtlir.Width = { + n match { + case UnknownBinaryPoint => firrtlir.UnknownWidth + case KnownBinaryPoint(w) => firrtlir.IntWidth(w) + } + } + + def getRangeWidth(w: Width): firrtlir.Width = { + if(w.known) { + firrtlir.IntWidth(w.get) + } + else { + firrtlir.UnknownWidth + } + } + def getRangeWidth(binaryPoint: BinaryPoint): firrtlir.Width = { + if(binaryPoint.known) { + firrtlir.IntWidth(binaryPoint.get) + } + else { + firrtlir.UnknownWidth + } + } + + //scalastyle:off method.name + def Unknown: IntervalRange = range"[?,?].?" +} + + +sealed class IntervalRange( + val lowerBound: firrtlir.Bound, + val upperBound: firrtlir.Bound, + private[chisel3] val firrtlBinaryPoint: firrtlir.Width) + extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) + with RangeType { + + (lowerBound, upperBound) match { + case (firrtlir.Open(begin), firrtlir.Open(end)) => + if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + binaryPoint match { + case KnownBinaryPoint(bp) => + if(begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { + throw new ChiselException(s"Invalid range with ${serialize}") + } + case _ => + } + case (firrtlir.Open(begin), firrtlir.Closed(end)) => + if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + case (firrtlir.Closed(begin), firrtlir.Open(end)) => + if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + case (firrtlir.Closed(begin), firrtlir.Closed(end)) => + if(begin > end) throw new ChiselException(s"Invalid range with ${serialize}") + case _ => + } + + //scalastyle:off cyclomatic.complexity + override def toString: String = { + val binaryPoint = firrtlBinaryPoint match { + case firrtlir.IntWidth(n) => s"$n" + case _ => "?" + } + val lowerBoundString = lowerBound match { + case firrtlir.Closed(l) => s"[$l" + case firrtlir.Open(l) => s"($l" + case firrtlir.UnknownBound => s"[?" + } + val upperBoundString = upperBound match { + case firrtlir.Closed(l) => s"$l]" + case firrtlir.Open(l) => s"$l)" + case firrtlir.UnknownBound => s"?]" + } + s"""range"$lowerBoundString,$upperBoundString.$binaryPoint"""" + } + + val increment: Option[BigDecimal] = firrtlBinaryPoint match { + case firrtlir.IntWidth(bp) => + Some(BigDecimal(math.pow(2, -bp.doubleValue))) + case _ => None + } + + /** If possible returns the lowest possible value for this Interval + * @return + */ + val getLowestPossibleValue: Option[BigDecimal] = { + increment match { + case Some(inc) => + lower match { + case firrtlir.Closed(n) => Some(n) + case firrtlir.Open(n) => Some(n + inc) + case _ => None + } + case _ => + None + } + } + + /** If possible returns the highest possible value for this Interval + * @return + */ + val getHighestPossibleValue: Option[BigDecimal] = { + increment match { + case Some(inc) => + lower match { + case firrtlir.Closed(n) => Some(n) + case firrtlir.Open(n) => Some(n - inc) + case _ => None + } + case _ => + None + } + } + + /** Return a Seq of the possible values for this range + * Mostly to be used for testing + * @return + */ + def getPossibleValues: Seq[BigDecimal] = { + (getLowestPossibleValue, getHighestPossibleValue, increment) match { + case (Some(low), Some(high), Some(inc)) => (low to high by inc) + case (_, _, None) => + throw new ChiselException(s"BinaryPoint unknown. Cannot get possible values from IntervalRange $toString") + case _ => + throw new ChiselException(s"Unknown Bound. Cannot get possible values from IntervalRange $toString") + + } + } + + override def getWidth: Width = { + width match { + case firrtlir.IntWidth(n) => KnownWidth(n.toInt) + case firrtlir.UnknownWidth => UnknownWidth() + } + } + + private def doFirrtlOp(op: firrtlir.PrimOp, that: IntervalRange): IntervalRange = { + PrimOps.set_primop_type( + firrtlir.DoPrim(op, + Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil,firrtlir.UnknownType) + ).tpe match { + case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) + case other => sys.error("BAD!") + } + } + + private def doFirrtlDynamicShift(that: UInt, isLeft: Boolean): IntervalRange = { + val uinttpe = that.widthOption match { + case None => firrtlir.UIntType(firrtlir.UnknownWidth) + case Some(w) => firrtlir.UIntType(firrtlir.IntWidth(w)) + } + val op = if(isLeft) PrimOps.Dshl else PrimOps.Dshr + PrimOps.set_primop_type( + firrtlir.DoPrim(op, + Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil,firrtlir.UnknownType) + ).tpe match { + case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) + case other => sys.error("BAD!") + } + } + + private def doFirrtlOp(op: firrtlir.PrimOp, that: Int): IntervalRange = { + PrimOps.set_primop_type( + firrtlir.DoPrim(op, + Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) + ).tpe match { + case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) + case other => sys.error("BAD!") + } + } + + /** Multiply this by that, here we return a fully unknown range, + * firrtl's range inference can figure this out + * @param that + * @return + */ + override def *(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Mul, that) + } + + /** Add that to this, here we return a fully unknown range, + * firrtl's range inference can figure this out + * @param that + * @return + */ + override def +&(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Add, that) + } + + /** Subtract that from this, here we return a fully unknown range, + * firrtl's range inference can figure this out + * @param that + * @return + */ + override def -&(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Sub, that) + } + + private def adjustBoundValue(value: BigDecimal, binaryPointValue: Int): BigDecimal = { + if(binaryPointValue >= 0) { + val maskFactor = BigDecimal(1 << binaryPointValue) + val a = (value * maskFactor) + val b = a.setScale(0, RoundingMode.DOWN) + val c = b / maskFactor + c + } else { + value + } + } + + private def adjustBound(bound: firrtlir.Bound, binaryPoint: BinaryPoint): firrtlir.Bound = { + binaryPoint match { + case KnownBinaryPoint(binaryPointValue) => + bound match { + case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) + case firrtlir.Closed(value) => firrtlir.Closed(adjustBoundValue(value, binaryPointValue)) + case _ => bound + } + case _ => firrtlir.UnknownBound + } + } + + /** Creates a new range with the increased precision + * + * @param newBinaryPoint + * @return + */ + def incPrecision(newBinaryPoint: BinaryPoint): IntervalRange = { + newBinaryPoint match { + case KnownBinaryPoint(that) => + doFirrtlOp(PrimOps.IncP, that) + case _ => + throwException(s"$this.incPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know") + } + } + + /** Creates a new range with the decreased precision + * + * @param newBinaryPoint + * @return + */ + def decPrecision(newBinaryPoint: BinaryPoint): IntervalRange = { + newBinaryPoint match { + case KnownBinaryPoint(that) => + doFirrtlOp(PrimOps.DecP, that) + case _ => + throwException(s"$this.decPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know") + } + } + + /** Creates a new range with the given binary point, adjusting precision + * on bounds as necessary + * + * @param newBinaryPoint + * @return + */ + def setPrecision(newBinaryPoint: BinaryPoint): IntervalRange = { + newBinaryPoint match { + case KnownBinaryPoint(that) => + doFirrtlOp(PrimOps.SetP, that) + case _ => + throwException(s"$this.setPrecision(newBinaryPoint = $newBinaryPoint) error, newBinaryPoint must be know") + } + } + + /** Shift this range left, i.e. shifts the min and max by the specified amount + * @param that + * @return + */ + override def <<(that: Int): IntervalRange = { + doFirrtlOp(PrimOps.Shl, that) + } + + /** Shift this range left, i.e. shifts the min and max by the known width + * @param that + * @return + */ + override def <<(that: KnownWidth): IntervalRange = { + <<(that.value) + } + + /** Shift this range left, i.e. shifts the min and max by value + * @param that + * @return + */ + def <<(that: UInt): IntervalRange = { + doFirrtlDynamicShift(that, isLeft = true) + } + + /** Shift this range right, i.e. shifts the min and max by the specified amount + * @param that + * @return + */ + override def >>(that: Int): IntervalRange = { + doFirrtlOp(PrimOps.Shr, that) + } + + /** Shift this range right, i.e. shifts the min and max by the known width + * @param that + * @return + */ + override def >>(that: KnownWidth): IntervalRange = { + >>(that.value) + } + + /** Shift this range right, i.e. shifts the min and max by value + * @param that + * @return + */ + def >>(that: UInt): IntervalRange = { + doFirrtlDynamicShift(that, isLeft = false) + } + + /** + * Squeeze returns the intersection of the ranges this interval and that Interval + * @param that + * @return + */ + def squeeze(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Squeeze, that) + } + + /** + * Wrap the value of this [[Interval]] into the range of a different Interval with a presumably smaller range. + * @param that + * @return + */ + def wrap(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Wrap, that) + } + + /** + * Clip the value of this [[Interval]] into the range of a different Interval with a presumably smaller range. + * @param that + * @return + */ + def clip(that: IntervalRange): IntervalRange = { + doFirrtlOp(PrimOps.Clip, that) + } + + /** merges the ranges of this and that, basically takes lowest low, highest high and biggest bp + * set unknown if any of this or that's value of above is unknown + * Like an union but will slurp up points in between the two ranges that were part of neither + * @param that + * @return + */ + override def merge(that: IntervalRange): IntervalRange = { + val lowest = (this.getLowestPossibleValue, that.getLowestPossibleValue) match { + case (Some(l1), Some(l2)) => + if(l1 < l2) { this.lower } else { that.lower } + case _ => + firrtlir.UnknownBound + } + val highest = (this.getHighestPossibleValue, that.getHighestPossibleValue) match { + case (Some(l1), Some(l2)) => + if(l1 >= l2) { this.lower } else { that.lower } + case _ => + firrtlir.UnknownBound + } + val newBinaryPoint = (this.firrtlBinaryPoint, that.firrtlBinaryPoint) match { + case (firrtlir.IntWidth(b1), firrtlir.IntWidth(b2)) => + if(b1 > b2) { firrtlir.IntWidth(b1)} else { firrtlir.IntWidth(b2) } + case _ => + firrtlir.UnknownWidth + } + IntervalRange(lowest, highest, newBinaryPoint) + } + + def binaryPoint: BinaryPoint = { + firrtlBinaryPoint match { + case firrtlir.IntWidth(n) => + assert(n < Int.MaxValue, s"binary point value $n is out of range") + KnownBinaryPoint(n.toInt) + case _ => UnknownBinaryPoint + } + } +} + abstract class Command { def sourceInfo: SourceInfo } |
