summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala4
-rw-r--r--src/test/scala/chiselTests/PopCount.scala27
2 files changed, 30 insertions, 1 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
index e87fb045..f15fb178 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
@@ -37,7 +37,9 @@ private[chisel3] object SeqUtils {
def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = in.size match {
case 0 => 0.U
case 1 => in.head
- case n => count(in take n/2) +& count(in drop n/2)
+ case n =>
+ val sum = count(in take n/2) +& count(in drop n/2)
+ sum(BigInt(n).bitLength - 1, 0)
}
/** Returns the data value corresponding to the first true predicate.
diff --git a/src/test/scala/chiselTests/PopCount.scala b/src/test/scala/chiselTests/PopCount.scala
new file mode 100644
index 00000000..d9b3b837
--- /dev/null
+++ b/src/test/scala/chiselTests/PopCount.scala
@@ -0,0 +1,27 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.util.PopCount
+import org.scalatest._
+import org.scalatest.prop._
+import chisel3.testers.BasicTester
+
+class PopCountTester(n: Int) extends BasicTester {
+ val x = RegInit(0.U(n.W))
+ x := x + 1.U
+ when (RegNext(x === ~0.U(n.W))) { stop() }
+
+ val result = PopCount(x.asBools)
+ val expected = x.asBools.foldLeft(0.U)(_ +& _)
+ assert(result === expected)
+
+ require(result.getWidth == BigInt(n).bitLength)
+}
+
+class PopCountSpec extends ChiselPropSpec {
+ property("Mul lookup table should return the correct result") {
+ forAll(smallPosInts) { (n: Int) => assertTesterPasses { new PopCountTester(n) } }
+ }
+}