summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala3
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala1
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala32
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Reg.scala3
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala12
-rw-r--r--src/main/scala/chisel3/compatibility.scala2
-rw-r--r--src/main/scala/chisel3/compatibility/debug.scala8
-rw-r--r--src/main/scala/chisel3/package.scala2
-rw-r--r--src/main/scala/chisel3/util/BitPat.scala3
-rw-r--r--src/main/scala/chisel3/util/Bitwise.scala15
-rw-r--r--src/main/scala/chisel3/util/CircuitMath.scala16
-rw-r--r--src/main/scala/chisel3/util/OneHot.scala2
-rw-r--r--src/test/scala/chiselTests/BetterNamingTests.scala101
-rw-r--r--src/test/scala/chiselTests/GCD.scala2
14 files changed, 166 insertions, 36 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
index 07c113fd..20ac0e4a 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -36,6 +36,7 @@ abstract class Element(private[core] val width: Width) extends Data {
def dir: Direction = binding.direction.get
private[chisel3] final def allElements: Seq[Element] = Seq(this)
+ def widthKnown: Boolean = width.known
}
/** A data type for values represented by a single bitvector. Provides basic
@@ -521,7 +522,7 @@ private[core] sealed trait UIntFactory {
/** Create a UInt port with specified width. */
def width(width: Width): UInt = new UInt(width)
/** Create a UInt with a specified width - compatibility with Chisel2. */
- def apply(dummy: Direction, width: Int): UInt = apply(Width(width))
+ def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width))
/** Create a UInt literal with fixed width. */
def apply(value: BigInt, width: Int): UInt = Lit(value, Width(width))
/** Create a UInt literal with inferred width. */
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index fee5c01c..9e362fa6 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -208,7 +208,6 @@ object Wire {
Binding.checkSynthesizable(init, s"'init' ($init)")
x := init
}
-
x
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
index e8474e39..a593f539 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -2,7 +2,7 @@
package chisel3.core
-import scala.collection.mutable.{ArrayBuffer, HashSet}
+import scala.collection.mutable.ArrayBuffer
import scala.language.experimental.macros
import chisel3.internal._
@@ -136,13 +136,35 @@ extends HasId {
}
// Suggest names to nodes using runtime reflection
- val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*)
+ 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
+ * Currently supported:
+ * - Iterable
+ * - Option
+ * (Note that Map is Iterable[Tuple2[_,_]] and thus excluded)
+ */
+ def nameRecursively(prefix: String, nameMe: Any): Unit =
+ nameMe match {
+ case (id: HasId) => id.suggestName(prefix)
+ case Some(elt) => nameRecursively(prefix, elt)
+ case (iter: Iterable[_]) if iter.hasDefiniteSize =>
+ for ((elt, i) <- iter.zipWithIndex) {
+ nameRecursively(s"${prefix}_${i}", elt)
+ }
+ case _ => // Do nothing
+ }
val methods = getClass.getMethods.sortWith(_.getName > _.getName)
- for (m <- methods; if isPublicVal(m)) m.invoke(this) match {
- case (id: HasId) => id.suggestName(m.getName)
- case _ =>
+ for (m <- methods if isPublicVal(m)) {
+ nameRecursively(m.getName, m.invoke(this))
}
// For Module instances we haven't named, suggest the name of the Module
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
index c1693531..f5706833 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
@@ -8,8 +8,7 @@ import chisel3.internal.firrtl._
import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
object Reg {
- private[core] def makeType[T <: Data](t: T = null, next: T = null,
-init: T = null): T = {
+ private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = {
if (t ne null) {
Binding.checkUnbound(t, s"t ($t) must be unbound Type. Try using cloneType?")
t.chiselCloneType
diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
index b06fd7a5..f4eec422 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
@@ -23,14 +23,10 @@ private[chisel3] object SeqUtils {
/** Counts the number of true Bools in a Seq */
def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg
- def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = {
- if (in.size == 0) {
- UInt.Lit(0)
- } else if (in.size == 1) {
- in.head
- } else {
- count(in.slice(0, in.size/2)) + (UInt.Lit(0) ## count(in.slice(in.size/2, in.size)))
- }
+ def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = in.size match {
+ case 0 => UInt.Lit(0)
+ case 1 => in.head
+ case n => count(in take n/2) +& count(in drop n/2)
}
/** Returns data value corresponding to first true predicate */
diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala
index 9360acbc..b7020b5e 100644
--- a/src/main/scala/chisel3/compatibility.scala
+++ b/src/main/scala/chisel3/compatibility.scala
@@ -63,7 +63,7 @@ package object Chisel {
val ImplicitConversions = chisel3.util.ImplicitConversions
val chiselMain = chisel3.compatibility.chiselMain
val throwException = chisel3.compatibility.throwException
- val debug = chisel3.core.debug
+ val debug = chisel3.compatibility.debug
object testers {
type BasicTester = chisel3.testers.BasicTester
diff --git a/src/main/scala/chisel3/compatibility/debug.scala b/src/main/scala/chisel3/compatibility/debug.scala
new file mode 100644
index 00000000..c3966dae
--- /dev/null
+++ b/src/main/scala/chisel3/compatibility/debug.scala
@@ -0,0 +1,8 @@
+package chisel3.compatibility
+
+import chisel3.core._
+
+@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3")
+object debug { // scalastyle:ignore object.name
+ def apply (arg: Data): Data = arg
+}
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala
index d47ed890..9a79b109 100644
--- a/src/main/scala/chisel3/package.scala
+++ b/src/main/scala/chisel3/package.scala
@@ -100,7 +100,7 @@ package object chisel3 {
implicit class fromBooleanToLiteral(val x: Boolean) extends AnyVal {
def B: Bool = Bool(x)
}
-
+
implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal {
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 3ae192a2..5b37bd1b 100644
--- a/src/main/scala/chisel3/util/BitPat.scala
+++ b/src/main/scala/chisel3/util/BitPat.scala
@@ -68,7 +68,8 @@ object BitPat {
*/
def apply(x: UInt): BitPat = {
require(x.isLit)
- BitPat("b" + x.litValue.toString(2))
+ val len = if (x.widthKnown) x.getWidth else 0
+ apply("b" + x.litValue.toString(2).reverse.padTo(len, "0").reverse.mkString)
}
}
diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala
index b2a9a28c..2743e59f 100644
--- a/src/main/scala/chisel3/util/Bitwise.scala
+++ b/src/main/scala/chisel3/util/Bitwise.scala
@@ -11,7 +11,7 @@ import chisel3.core.SeqUtils
object FillInterleaved
{
def apply(n: Int, in: UInt): UInt = apply(n, in.toBools)
- def apply(n: Int, in: Seq[Bool]): UInt = Vec(in.map(Fill(n, _))).toBits
+ def apply(n: Int, in: Seq[Bool]): UInt = Cat(in.map(Fill(n, _)).reverse)
}
/** Returns the number of bits set (i.e value is 1) in the input signal.
@@ -29,22 +29,17 @@ object Fill {
n match {
case 0 => UInt.width(0)
case 1 => x
- case y if n > 1 =>
+ case _ if x.widthKnown && x.getWidth == 1 =>
+ Mux(x.toBool, UInt((BigInt(1) << n) - 1, n), UInt(0, n))
+ case _ if n > 1 =>
val p2 = Array.ofDim[UInt](log2Up(n + 1))
p2(0) = x
for (i <- 1 until p2.length)
p2(i) = Cat(p2(i-1), p2(i-1))
- Cat((0 until log2Up(y + 1)).filter(i => (y & (1 << i)) != 0).map(p2(_)))
+ Cat((0 until log2Up(n + 1)).filter(i => (n & (1 << i)) != 0).map(p2(_)))
case _ => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.")
}
}
- /** Fan out x n times */
- def apply(n: Int, x: Bool): UInt =
- if (n > 1) {
- UInt(0,n) - x
- } else {
- apply(n, x: UInt)
- }
}
/** Litte/big bit endian convertion: reverse the order of the bits in a UInt.
diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala
index 8f8bde4a..27bd7bfb 100644
--- a/src/main/scala/chisel3/util/CircuitMath.scala
+++ b/src/main/scala/chisel3/util/CircuitMath.scala
@@ -7,11 +7,11 @@ package chisel3.util
import chisel3._
-/** Compute Log2 with truncation of a UInt in hardware using a Mux Tree
- * An alternative interpretation is it computes the minimum number of bits needed to represent x
+/** Compute the base-2 integer logarithm of a UInt
* @example
* {{{ data_out := Log2(data_in) }}}
- * @note Truncation is used so Log2(UInt.Lit(12412)) = 13*/
+ * @note The result is truncated, so e.g. Log2(13.U) = 3
+ */
object Log2 {
/** Compute the Log2 on the least significant n bits of x */
def apply(x: Bits, width: Int): UInt = {
@@ -19,10 +19,18 @@ object Log2 {
UInt.Lit(0)
} else if (width == 2) {
x(1)
+ } else if (width <= divideAndConquerThreshold) {
+ Mux(x(width-1), UInt.Lit(width-1), apply(x, width-1))
} else {
- Mux(x(width-1), UInt.width(width-1), apply(x, width-1))
+ val mid = 1 << (log2Ceil(width) - 1)
+ val hi = x(width-1, mid)
+ val lo = x(mid-1, 0)
+ val useHi = hi.orR
+ Cat(useHi, Mux(useHi, Log2(hi, width - mid), Log2(lo, mid)))
}
}
def apply(x: Bits): UInt = apply(x, x.getWidth)
+
+ private def divideAndConquerThreshold = 4
}
diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala
index c1f94ba6..49661115 100644
--- a/src/main/scala/chisel3/util/OneHot.scala
+++ b/src/main/scala/chisel3/util/OneHot.scala
@@ -10,7 +10,7 @@ import chisel3._
/** Converts from One Hot Encoding to a UInt indicating which bit is active
* This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/
object OHToUInt {
- def apply(in: Seq[Bool]): UInt = apply(Vec(in))
+ def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size)
def apply(in: Vec[Bool]): UInt = apply(in.toBits, in.size)
def apply(in: Bits): UInt = apply(in, in.getWidth)
diff --git a/src/test/scala/chiselTests/BetterNamingTests.scala b/src/test/scala/chiselTests/BetterNamingTests.scala
new file mode 100644
index 00000000..44fc542a
--- /dev/null
+++ b/src/test/scala/chiselTests/BetterNamingTests.scala
@@ -0,0 +1,101 @@
+package chiselTests
+
+import org.scalatest.{FlatSpec, Matchers}
+import collection.mutable
+
+import Chisel._
+
+
+// Defined outside of the class so we don't get $ in name
+class Other(w: Int) extends Module {
+ val io = new Bundle {
+ val a = UInt(width = w)
+ }
+}
+class PerNameIndexing(count: Int) extends Module {
+ val io = new Bundle { }
+
+ val wires = Seq.tabulate(count) { i => Module(new Other(i)) }
+ val queues = Seq.tabulate(count) { i => Module(new Queue(UInt(width = i), 16)) }
+}
+
+// Note this only checks Iterable[Chisel.Data] which excludes Maps
+class IterableNaming extends Module {
+ val io = new Bundle { }
+
+ val seq = Seq.tabulate(3) { i =>
+ Seq.tabulate(2) { j => Wire(init = (i * j).U) }
+ }
+ val optSet = Some(Set(Wire(init = 0.U),
+ Wire(init = 1.U),
+ Wire(init = 2.U),
+ Wire(init = 3.U)))
+
+ val stack = mutable.Stack[Module]()
+ for (i <- 0 until 4) {
+ stack push Module(new Other(i))
+ }
+
+ def streamFrom(x: Int): Stream[Module] =
+ Module(new Other(x)) #:: streamFrom(x + 1)
+ val stream = streamFrom(0) // Check that we don't get into infinite loop
+ val list = stream.take(8).toList
+}
+
+/* Better Naming Tests
+ *
+ * These tests are intended to validate that Chisel picks better names
+ */
+class BetterNamingTests extends FlatSpec {
+
+ behavior of "Better Naming"
+
+ it should "provide unique counters for each name" in {
+ val verilog = Driver.emit(() => new PerNameIndexing(4))
+ val ModuleDef = """\s*module\s+(\S+)\s+:\s*""".r
+ val expectedModules = Set("PerNameIndexing",
+ "Queue", "Queue_1", "Queue_2", "Queue_3",
+ "Other", "Other_1", "Other_2", "Other_3")
+ val foundModules = for {
+ ModuleDef(name) <- verilog.split("\n").toSeq
+ } yield name
+ assert(foundModules.toSet === expectedModules)
+ }
+
+ it should "provide names for things defined in Iterable[HasId] and Option[HasId]" in {
+ val verilog = Driver.emit(() => new IterableNaming)
+
+ val lines = verilog.split("\n").toSeq
+
+ val SeqDef = """\s*wire\s+seq_(\d+)_(\d+)\s+:\s+UInt\s*""".r
+ val seqs = for {
+ i <- (0 until 3)
+ j <- (0 until 2)
+ } yield (i.toString, j.toString)
+ val foundSeqs = for {
+ SeqDef(i, j) <- lines
+ } yield (i, j)
+ assert(foundSeqs.toSet === seqs.toSet)
+
+ val OptSetDef = """\s*wire\s+optSet_(\d+)\s+:\s+UInt\s*""".r
+ val optSets = (0 until 4) map (_.toString)
+ val foundOptSets = for {
+ OptSetDef(i) <- lines
+ } yield i
+ assert(foundOptSets.toSet === optSets.toSet)
+
+ val StackDef = """\s*inst\s+stack_(\d+)\s+of\s+Other.*""".r
+ val stacks = (0 until 4) map (_.toString)
+ val foundStacks = for {
+ StackDef(i) <- lines
+ } yield i
+ assert(foundStacks.toSet === stacks.toSet)
+
+ val ListDef = """\s*inst\s+list_(\d+)\s+of\s+Other.*""".r
+ val lists = (0 until 8) map (_.toString)
+ val foundLists = for {
+ ListDef(i) <- lines
+ } yield i
+ assert(foundLists.toSet === lists.toSet)
+ }
+}
diff --git a/src/test/scala/chiselTests/GCD.scala b/src/test/scala/chiselTests/GCD.scala
index 5e4c897a..d683ce34 100644
--- a/src/test/scala/chiselTests/GCD.scala
+++ b/src/test/scala/chiselTests/GCD.scala
@@ -30,7 +30,7 @@ class GCDTester(a: Int, b: Int, z: Int) extends BasicTester {
dut.io.a := a.U
dut.io.b := b.U
dut.io.e := first
- when(first) { first := false.B }
+ when(first) { first := Bool(false) }
when(!first && dut.io.v) {
assert(dut.io.z === z.U)
stop()