diff options
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | build.sbt | 36 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 43 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 234 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Data.scala | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Module.scala | 12 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | 12 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala | 47 | ||||
| -rw-r--r-- | src/main/scala/chisel3/Driver.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/chisel3/package.scala | 7 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/BitPat.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BundleWire.scala | 28 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/FixedPointSpec.scala | 41 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Vec.scala | 6 |
15 files changed, 410 insertions, 68 deletions
@@ -2,7 +2,8 @@ Chisel3 is a new FIRRTL based chisel. It is currently in ALPHA VERSION, so many Chisel features may change in the coming months. -*TODO: A better description, perhaps lifted off Chisel2's README* +Please visit the [Wiki](https://github.com/ucb-bar/chisel3/wiki) for a more +detailed description. ## Chisel2 Migration For those moving from Chisel2, there were some backwards incompatible changes @@ -64,25 +64,25 @@ lazy val chiselSettings = Seq ( Resolver.sonatypeRepo("releases") ), - libraryDependencies ++= (Seq("firrtl").map { - dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }), - - -/* Bumping "com.novocode" % "junit-interface" % "0.11", causes DelayTest testSeqReadBundle to fail - * in subtly disturbing ways on Linux (but not on Mac): - * - some fields in the generated .h file are re-named, - * - an additional field is added - * - the generated .cpp file has additional differences: - * - different temps in clock_lo - * - missing assignments - * - change of assignment order - * - use of "Tx" vs. "Tx.values" - */ - libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.5" % "test", - libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, - libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.4" % "test", - libraryDependencies += "com.github.scopt" %% "scopt" % "3.4.0", + libraryDependencies ++= Seq( + "org.scalatest" %% "scalatest" % "2.2.5" % "test", + "org.scala-lang" % "scala-reflect" % scalaVersion.value, + "org.scalacheck" %% "scalacheck" % "1.12.4" % "test", + "com.github.scopt" %% "scopt" % "3.4.0" + ), + // Since we want to examine the classpath to determine if a dependency on firrtl is required, + // this has to be a Task setting. + // Fortunately, allDependencies is a Task Setting, so we can modify that. + allDependencies := { + allDependencies.value ++ Seq("firrtl").collect { + // If we have an unmanaged jar file on the classpath, assume we're to use that, + case dep: String if !(unmanagedClasspath in Compile).value.toString.contains(s"$dep.jar") => + // otherwise let sbt fetch the appropriate version. + "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) + } + }, + // Tests from other projects may still run concurrently. parallelExecution in Test := true, diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 9d8a9061..677fa43e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -19,6 +19,8 @@ sealed abstract class Aggregate extends Data { private[core] def width: Width = flatten.map(_.width).reduce(_ + _) private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) + + override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = SeqUtils.do_asUInt(this.flatten) } object Vec { @@ -351,24 +353,10 @@ class Bundle extends Aggregate { /** Returns a field's contained user-defined Bundle element if it appears to * be one, otherwise returns None. */ - private def getBundleField(m: java.lang.reflect.Method): Option[Data] = { - if (isBundleField(m) && - (classOf[Data].isAssignableFrom(m.getReturnType) || - classOf[Option[_]].isAssignableFrom(m.getReturnType))) { - m.invoke(this) match { - case d: Data => - Some(d) - case o: Option[_] => - o.getOrElse(None) match { - case d: Data => - Some(d) - case _ => None - } - case _ => None - } - } else { - None - } + private def getBundleField(m: java.lang.reflect.Method): Option[Data] = m.invoke(this) match { + case d: Data => Some(d) + case Some(d: Data) => Some(d) + case _ => None } /** Returns a list of elements in this Bundle. @@ -376,15 +364,14 @@ class Bundle extends Aggregate { private[core] lazy val namedElts = { val nameMap = LinkedHashMap[String, Data]() val seen = HashSet[Data]() - for (m <- getClass.getMethods.sortWith(_.getName < _.getName)) { - getBundleField(m) match { - case Some(d) => - if (nameMap contains m.getName) { - require(nameMap(m.getName) eq d) - } else if (!seen(d)) { - nameMap(m.getName) = d; seen += d - } - case None => + for (m <- getPublicFields(classOf[Bundle])) { + getBundleField(m) foreach { d => + if (nameMap contains m.getName) { + require(nameMap(m.getName) eq d) + } else if (!seen(d)) { + nameMap(m.getName) = d + seen += d + } } } ArrayBuffer(nameMap.toSeq:_*) sortWith {case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn))} @@ -397,8 +384,6 @@ class Bundle extends Aggregate { s"{${namedElts.reverse.map(e => eltPort(e._2)).mkString(", ")}}" } private[chisel3] lazy val flatten = namedElts.flatMap(_._2.flatten) - private[core] def addElt(name: String, elt: Data): Unit = - namedElts += name -> elt private[chisel3] override def _onModuleClose: Unit = // scalastyle:ignore method.name for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 741f6aee..7ee11b92 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -250,6 +250,18 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) def do_asSInt(implicit sourceInfo: SourceInfo): SInt + /** Reinterpret cast as a FixedPoint. + * + * @note value not guaranteed to be preserved: for example, an UInt of width + * 3 and value 7 (0b111) would become a FixedInt with value -1, the interpretation + * of the number is also affected by the specified binary point. Caution advised + */ + final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg + + def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = { + throwException(s"Cannot call .asFixedPoint on $this") + } + /** Reinterpret cast to Bits. */ @deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3") final def asBits(): Bits = macro SourceInfoTransform.noArg @@ -282,9 +294,6 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref)) } - @deprecated("Use asUInt, which does the same thing but makes the reinterpret cast more explicit", "chisel3") - override def toBits: UInt = do_asUInt(DeprecatedSourceInfo) - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = { val res = Wire(this, null).asInstanceOf[this.type] res := that @@ -463,6 +472,7 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that) override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that) + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") final def != (that: UInt): Bool = macro SourceInfoTransform.thatArg final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg @@ -510,6 +520,15 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref)) override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = this + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = { + binaryPoint match { + case KnownBinaryPoint(value) => + val iLit = ILit(value) + pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit)) + case _ => + throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint") + } + } } // This is currently a factory because both Bits and UInt inherit it. @@ -658,6 +677,7 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that) override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that) + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") final def != (that: SInt): Bool = macro SourceInfoTransform.thatArg final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg @@ -685,6 +705,9 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = this + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = { + pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref)) + } } object SInt { @@ -853,3 +876,208 @@ object Mux { } } +//scalastyle:off number.of.methods +/** + * A sealed class representing a fixed point number that has a bit width and a binary point + * The width and binary point may be inferred. + * + * IMPORTANT: The API provided here is experimental and may change in the future. + * + * @param width bit width of the fixed point number + * @param binaryPoint the position of the binary point with respect to the right most bit of the width + * currently this should be positive but it is hoped to soon support negative points + * and thus use this field as a simple exponent + * @param lit + */ +sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit: Option[FPLit] = None) + extends Bits(width, lit) with Num[FixedPoint] { + private[core] override def cloneTypeWidth(w: Width): this.type = + new FixedPoint(w, binaryPoint).asInstanceOf[this.type] + private[chisel3] def toType = s"Fixed$width$binaryPoint" + + def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match { + case _: FixedPoint => this connect that + case _ => this badConnect that + } + + private[chisel3] def fromInt(value: BigInt, width: Int): this.type = { + throwException(s"Don't use $this.fromInt($value, $width): Use literal constructors instead") + } + + final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg + final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg + + def unary_- (implicit sourceInfo: SourceInfo): FixedPoint = FixedPoint.fromBigInt(0) - this + def unary_-% (implicit sourceInfo: SourceInfo): FixedPoint = FixedPoint.fromBigInt(0) -% this + + /** add (default - no growth) operator */ + override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + this +% that + /** subtract (default - no growth) operator */ + override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + this -% that + override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that) + override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"division is illegal on FixedPoint types") + override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"mod is illegal on FixedPoint types") + + final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + def do_* (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + def do_* (that: SInt)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + /** add (width +1) operator */ + final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + /** add (no growth) operator */ + final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ + final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ + final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint((this.width max that.width) + 1, this.binaryPoint max that.binaryPoint), AddOp, that) + def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint((this.width max that.width) + 1, this.binaryPoint max that.binaryPoint), SubOp, that) + def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + + final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"And is illegal between $this and $that") + def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"Or is illegal between $this and $that") + def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"Xor is illegal between $this and $that") + + final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg + + def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width, KnownBinaryPoint(that)), SetBinaryPoint, that) + + /** Returns this wire bitwise-inverted. */ + def do_unary_~ (implicit sourceInfo: SourceInfo): FixedPoint = + throwException(s"Not is illegal on $this") + + // TODO(chick): Consider comparison with UInt and SInt + override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that) + override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that) + override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that) + override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that) + + final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that) + def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that) + def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that) + + final def abs(): UInt = macro SourceInfoTransform.noArg + + def do_abs(implicit sourceInfo: SourceInfo): UInt = { + Mux(this < FixedPoint.fromBigInt(0), (FixedPoint.fromBigInt(0)-this).asUInt, this.asUInt) + } + + override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, that) + override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): FixedPoint = + this << that.toInt + override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that) + override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, that) + override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): FixedPoint = + this >> that.toInt + override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint = + binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that) + + override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) + //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt +} + +/** Use PrivateObject to force users to specify width and binaryPoint by name + */ +sealed trait PrivateType +private case object PrivateObject extends PrivateType + +/** + * Factory and convenience methods for the FixedPoint class + * IMPORTANT: The API provided here is experimental and may change in the future. + */ +object FixedPoint { + /** Create an FixedPoint type with inferred width. */ + def apply(): FixedPoint = apply(Width(), BinaryPoint()) + + /** Create an FixedPoint type or port with fixed width. */ + def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint)) + /** Create an FixedPoint port with inferred width. */ + def apply(dir: Direction): FixedPoint = apply(dir, Width(), BinaryPoint()) + + /** Create an FixedPoint literal with inferred width from BigInt. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromBigInt(value: BigInt, width: Int = -1, binaryPoint: Int = 0): FixedPoint = + if(width == -1) { + apply(value, Width(), BinaryPoint(binaryPoint)) + } + else { + apply(value, Width(width), BinaryPoint(binaryPoint)) + } + /** Create an FixedPoint literal with inferred width from Double. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromDouble(value: Double, dummy: PrivateType = PrivateObject, + width: Int = -1, binaryPoint: Int = 0): FixedPoint = { + fromBigInt( + toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + ) + } + + /** Create an FixedPoint type with specified width and binary position. */ + def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint) + /** Create an FixedPoint port with specified width and binary position. */ + def apply(dir: Direction, width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint) + def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = { + val lit = FPLit(value, width, binaryPoint) + val newLiteral = new FixedPoint(lit.width, lit.binaryPoint, Some(lit)) + newLiteral.binding = LitBinding() + newLiteral + } + + /** + * How to create a bigint from a double with a specific binaryPoint + * @param x a double value + * @param binaryPoint a binaryPoint that you would like to use + * @return + */ + def toBigInt(x: Double, binaryPoint : Int): BigInt = { + val multiplier = math.pow(2,binaryPoint ) + val result = BigInt(math.round(x * multiplier)) + result + } + + /** + * converts a bigInt with the given binaryPoint into the double representation + * @param i a bigint + * @param binaryPoint the implied binaryPoint of @i + * @return + */ + def toDouble(i: BigInt, binaryPoint : Int): Double = { + val multiplier = math.pow(2,binaryPoint ) + val result = i.toDouble / multiplier + result + } + +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index bd2e9065..86858e5d 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -254,7 +254,7 @@ abstract class Data extends HasId { * * This performs the inverse operation of fromBits(Bits). */ - @deprecated("Use asUInt, which does the same thing but makes the reinterpret cast more explicit", "chisel3") + @deprecated("Best alternative, .toUInt() or if Bits really needed, .toUInt().toBits()", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) /** Reinterpret cast to UInt. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index 55522b4a..c700dc1b 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -162,15 +162,6 @@ extends HasId { port.setRef(ModuleIO(this, _namespace.name(name))) } - // Suggest names to nodes using runtime reflection - def getValNames(c: Class[_]): Set[String] = { - if (c == classOf[Module]) Set() - else getValNames(c.getSuperclass) ++ c.getDeclaredFields.map(_.getName) - } - val valNames = getValNames(this.getClass) - def isPublicVal(m: java.lang.reflect.Method) = - m.getParameterTypes.isEmpty && valNames.contains(m.getName) - /** Recursively suggests names to supported "container" classes * Arbitrary nestings of supported classes are allowed so long as the * innermost element is of type HasId @@ -189,8 +180,7 @@ extends HasId { } case _ => // Do nothing } - val methods = getClass.getMethods.sortWith(_.getName > _.getName) - for (m <- methods if isPublicVal(m)) { + for (m <- getPublicFields(classOf[Module])) { nameRecursively(m.getName, m.invoke(this)) } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 12cc840e..b4b0e028 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -127,6 +127,18 @@ private[chisel3] trait HasId extends InstanceId { case Some(p) => p.modName case None => throwException(s"$instanceName doesn't have a parent") } + + private[chisel3] def getPublicFields(rootClass: Class[_]): Seq[java.lang.reflect.Method] = { + // Suggest names to nodes using runtime reflection + def getValNames(c: Class[_]): Set[String] = { + if (c == rootClass) Set() + else getValNames(c.getSuperclass) ++ c.getDeclaredFields.map(_.getName) + } + val valNames = getValNames(this.getClass) + def isPublicVal(m: java.lang.reflect.Method) = + m.getParameterTypes.isEmpty && valNames.contains(m.getName) + this.getClass.getMethods.sortWith(_.getName < _.getName).filter(isPublicVal(_)) + } } private[chisel3] class DynamicContext() { diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 0641686c..0f866c27 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -42,6 +42,8 @@ object PrimOp { val ConvertOp = PrimOp("cvt") val AsUIntOp = PrimOp("asUInt") val AsSIntOp = PrimOp("asSInt") + val AsFixedPointOp = PrimOp("asFixedPoint") + val SetBinaryPoint = PrimOp("bpset") val AsClockOp = PrimOp("asClock") } @@ -85,6 +87,14 @@ case class SLit(n: BigInt, w: Width) extends LitArg(n, w) { def minWidth: Int = 1 + n.bitLength } +case class FPLit(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"asFixedPoint(${ULit(unsigned, width).name}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})" + } + def minWidth: Int = 1 + n.bitLength +} + case class Ref(name: String) extends Arg case class ModuleIO(mod: Module, name: String) extends Arg { override def fullName(ctx: Component): String = @@ -136,6 +146,43 @@ sealed case class KnownWidth(value: Int) extends Width { override def toString: String = s"<${value.toString}>" } +object BinaryPoint { + def apply(x: Int): BinaryPoint = KnownBinaryPoint(x) + def apply(): BinaryPoint = UnknownBinaryPoint +} + +sealed abstract class BinaryPoint { + type W = Int + def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) + def + (that: BinaryPoint): BinaryPoint = this.op(that, _ + _) + def + (that: Int): BinaryPoint = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0 max (a - that)) + def dynamicShiftLeft(that: BinaryPoint): BinaryPoint = + this.op(that, (a, b) => a + (1 << b) - 1) + + def known: Boolean + def get: W + protected def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint +} + +case object UnknownBinaryPoint extends BinaryPoint { + def known: Boolean = false + def get: Int = None.get + def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = this + override def toString: String = "" +} + +sealed case class KnownBinaryPoint(value: Int) extends BinaryPoint { + def known: Boolean = true + def get: Int = value + def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = that match { + case KnownBinaryPoint(x) => KnownBinaryPoint(f(value, x)) + case _ => that + } + override def toString: String = s"<<${value.toString}>>" +} + + sealed abstract class MemPortDirection(name: String) { override def toString: String = name } diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index dbd9b464..a0713379 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -119,13 +119,13 @@ trait BackendCompilationUtilities { "-Wno-WIDTH", "-Wno-STMTDLY", "--trace", - "-O2", + "-O0", "--top-module", topModule, "+define+TOP_TYPE=V" + dutFile, s"+define+PRINTF_COND=!$topModule.reset", s"+define+STOP_COND=!$topModule.reset", "-CFLAGS", - s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", + s"""-Wno-undefined-bool-conversion -O0 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", "-Mdir", dir.toString, "--exe", cppHarness.toString) System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 0a57b7de..e0364868 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -37,6 +37,8 @@ package object chisel3 { // scalastyle:ignore package.object.name val UInt = chisel3.core.UInt type SInt = chisel3.core.SInt val SInt = chisel3.core.SInt + type FixedPoint = chisel3.core.FixedPoint + val FixedPoint = chisel3.core.FixedPoint type Bool = chisel3.core.Bool val Bool = chisel3.core.Bool val Mux = chisel3.core.Mux @@ -150,8 +152,13 @@ package object chisel3 { // scalastyle:ignore package.object.name def B: Bool = Bool(x) // scalastyle:ignore method.name } + implicit class fromDoubleToLiteral(val x: Double) extends AnyVal { + def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(x, binaryPoint = binaryPoint) + } + implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal { final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 972010a6..e58258c7 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -82,6 +82,7 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { def getWidth: Int = width def === (that: UInt): Bool = macro SourceInfoTransform.thatArg def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") def != (that: UInt): Bool = macro SourceInfoTransform.thatArg def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = value.asUInt === (that & mask.asUInt) // scalastyle:ignore method.name diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index a0cbf4f7..c9d57759 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -145,6 +145,8 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle val deq = EnqIO(gen) /** The current amount of data in the queue */ val count = Output(UInt.width(log2Up(entries + 1))) + + override def cloneType = new QueueIO(gen, entries).asInstanceOf[this.type] } /** A hardware module implementing a Queue diff --git a/src/test/scala/chiselTests/BundleWire.scala b/src/test/scala/chiselTests/BundleWire.scala index 53d46e93..5b38ff6e 100644 --- a/src/test/scala/chiselTests/BundleWire.scala +++ b/src/test/scala/chiselTests/BundleWire.scala @@ -24,6 +24,27 @@ class BundleWire(n: Int) extends Module { } } +class BundleToUnitTester extends BasicTester { + val bundle1 = Wire(new Bundle { + val a = UInt(width = 4) + val b = UInt(width = 4) + }) + val bundle2 = Wire(new Bundle { + val a = UInt(width = 2) + val b = UInt(width = 6) + }) + + // 0b00011011 split as 0001 1011 and as 00 011011 + bundle1.a := 1.U + bundle1.b := 11.U + bundle2.a := 0.U + bundle2.b := 27.U + + assert(bundle1.asUInt() === bundle2.asUInt()) + + stop() +} + class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester { val dut = Module(new BundleWire(n)) dut.io.in.x := UInt(x) @@ -43,3 +64,10 @@ class BundleWireSpec extends ChiselPropSpec { } } } + +class BundleToUIntSpec extends ChiselPropSpec { + property("Bundles with same data but different, underlying elements should compare as UInt") { + assertTesterPasses( new BundleToUnitTester ) + } +} + diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala new file mode 100644 index 00000000..69015e42 --- /dev/null +++ b/src/test/scala/chiselTests/FixedPointSpec.scala @@ -0,0 +1,41 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.testers.BasicTester +import org.scalatest._ + +//scalastyle:off magic.number +class FixedPointSpec extends FlatSpec with Matchers { + behavior of "fixed point utilities" + + they should "allow conversion between doubles and the bigints needed to represent them" in { + val initialDouble = 0.125 + val bigInt = FixedPoint.toBigInt(initialDouble, 4) + val finalDouble = FixedPoint.toDouble(bigInt, 4) + + initialDouble should be(finalDouble) + } +} + +class SBP extends Module { + val io = IO(new Bundle { + val in = Input(FixedPoint(6, 2)) + val out = Output(FixedPoint(4, 0)) + }) + io.out := io.in.setBinaryPoint(0) +} +class SBPTester extends BasicTester { + val dut = Module(new SBP) + dut.io.in := FixedPoint.fromDouble(3.75, binaryPoint = 2) + + assert(dut.io.out === FixedPoint.fromDouble(3.0, binaryPoint = 0)) + + stop() +} +class SBPSpec extends ChiselPropSpec { + property("should allow set binary point") { + assertTesterPasses { new SBPTester } + } +} diff --git a/src/test/scala/chiselTests/Vec.scala b/src/test/scala/chiselTests/Vec.scala index c5447610..0d5a2188 100644 --- a/src/test/scala/chiselTests/Vec.scala +++ b/src/test/scala/chiselTests/Vec.scala @@ -23,9 +23,9 @@ class TabulateTester(n: Int) extends BasicTester { val x = Vec(Array.tabulate(n){ i => UInt(i * 2) }) val u = Vec.tabulate(n)(i => UInt(i*2)) - assert(v.toBits === x.toBits) - assert(v.toBits === u.toBits) - assert(x.toBits === u.toBits) + assert(v.asUInt() === x.asUInt()) + assert(v.asUInt() === u.asUInt()) + assert(x.asUInt() === u.asUInt()) stop() } |
