diff options
| author | Andrew Waterman | 2019-04-12 17:51:04 -0700 |
|---|---|---|
| committer | edwardcwang | 2019-04-15 13:07:11 -0700 |
| commit | a4a29e29c3f1eed18f851dcf10bdc845571dfcb6 (patch) | |
| tree | 876999a0301d4ef86e8bb0712e8bc3ec3d2f9ef7 | |
| parent | 0028c64922a85087b2b6a6062fe202294e70855a (diff) | |
Avoid silently truncating BigInt to Int
- Introduce internal helper `castToInt`, which issues an error when the input
BigInt can't be represented as Int.
- Use `castToInt` wherever we were using `toInt` in a potentially unsafe way.
3 files changed, 19 insertions, 10 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 43a851ed..e35d12f0 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -162,7 +162,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi // This preserves old behavior while a more more consistent API is under debate // See https://github.com/freechipsproject/chisel3/issues/867 litOption.map { value => - (((value >> x.toInt) & 1) == 1).asBool + (((value >> castToInt(x, "Index")) & 1) == 1).asBool }.getOrElse { requireIsHardware(this, "bits to be indexed") pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) @@ -238,7 +238,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @group SourceInfoTransformMacro */ final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - apply(x.toInt, y.toInt) + apply(castToInt(x, "High index"), castToInt(y, "Low index")) private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { requireIsHardware(this, "bits operated on") @@ -866,13 +866,13 @@ sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - this << that.toInt + this << castToInt(that, "Shift amount") override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - this >> that.toInt + this >> castToInt(that, "Shift amount") override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that) @@ -1155,13 +1155,13 @@ sealed class SInt private[core] (width: Width) extends Bits(width) with Num[SInt override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - this << that.toInt + this << castToInt(that, "Shift amount") override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - this >> that.toInt + this >> castToInt(that, "Shift amount") override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that) @@ -1602,13 +1602,13 @@ sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint) override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, validateShiftAmount(that)) override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this << that.toInt).asFixedPoint(this.binaryPoint) + (this << castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that) override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, validateShiftAmount(that)) override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this >> that.toInt).asFixedPoint(this.binaryPoint) + (this >> castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 4105a699..1163171c 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -378,3 +378,12 @@ object DynamicNamingStack { prefixRef } } + +/** Casts BigInt to Int, issuing an error when the input isn't representable. */ +private[chisel3] object castToInt { + def apply(x: BigInt, msg: String): Int = { + val res = x.toInt + require(x == res, s"$msg $x is too large to be represented as Int") + res + } +} diff --git a/src/main/scala/chisel3/internal/firrtl/Converter.scala b/src/main/scala/chisel3/internal/firrtl/Converter.scala index ee9d3a99..9366bea2 100644 --- a/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -6,7 +6,7 @@ import chisel3.core.{SpecifiedDirection, EnumType} import chisel3.experimental._ import chisel3.internal.sourceinfo.{NoSourceInfo, SourceLine, SourceInfo} import firrtl.{ir => fir} -import chisel3.internal.throwException +import chisel3.internal.{castToInt, throwException} import scala.annotation.tailrec import scala.collection.immutable.{Queue} @@ -50,7 +50,7 @@ private[chisel3] object Converter { case Slot(imm, name) => fir.SubField(convert(imm, ctx), name, fir.UnknownType) case Index(imm, ILit(idx)) => - fir.SubIndex(convert(imm, ctx), idx.toInt, fir.UnknownType) + fir.SubIndex(convert(imm, ctx), castToInt(idx, "Index"), fir.UnknownType) case Index(imm, value) => fir.SubAccess(convert(imm, ctx), convert(value, ctx), fir.UnknownType) case ModuleIO(mod, name) => |
