From 3668532fabc4ba4eaf70cf0ad1a55522aa33cdb3 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Tue, 11 Aug 2020 10:28:15 -0700 Subject: Restore Counter.n API (#1546) Includes special case support for Counter(0) which has identical behavior to Counter(1) except for the value of n.--- src/main/scala/chisel3/util/Counter.scala | 26 ++++++++++++++++++++++++-- src/test/scala/chiselTests/Counter.scala | 8 ++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 11daa515..fa1bb80c 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -19,20 +19,42 @@ import chisel3.internal.naming.chiselName // can't use chisel3_ version because * ... * } * }}} + * @example {{{ + * // Using Scala Range API + * val (counterValue, counterWrap) = Counter(0 until 10 by 2) + * when (counterValue === 4.U) { + * ... + * } + * }}} */ @chiselName -class Counter private (r: Range) { +class Counter private (r: Range, oldN: Option[Int] = None) { require(r.length > 0, s"Counter range cannot be empty, got: $r") require(r.start >= 0 && r.end >= 0, s"Counter range must be positive, got: $r") private lazy val delta = math.abs(r.step) private lazy val width = math.max(log2Up(r.last + 1), log2Up(r.head + 1)) + /** Number of counts before the counter resets + * + * @note Only defined for ranges starting at zero with steps of size 1. Use [[range]] for other + * use cases. + */ + def n: Int = oldN match { + case Some(x) => x + case None => + // Reasonable for typical ranges + require(r.start == 0 && r.step == 1, + s"Counter.n only defined on ranges starting at 0 with step == 1, got $r. " + + "Use underlying range.") + r.last + 1 + } + /** Creates a counter with the specified number of steps. * * @param n number of steps before the counter resets */ - def this(n: Int) { this(0 until math.max(1, n)) } + def this(n: Int) { this(0 until math.max(1, n), Some(n)) } /** The current value of the counter. */ val value = if (r.length > 1) RegInit(r.head.U(width.W)) else r.head.U diff --git a/src/test/scala/chiselTests/Counter.scala b/src/test/scala/chiselTests/Counter.scala index 31bfe7eb..985cf3fd 100644 --- a/src/test/scala/chiselTests/Counter.scala +++ b/src/test/scala/chiselTests/Counter.scala @@ -8,8 +8,10 @@ import chisel3.util._ class CountTester(max: Int) extends BasicTester { val cnt = Counter(max) + assert(cnt.n == max) when(true.B) { cnt.inc() } - when(cnt.value === (max-1).asUInt) { + val expected = if (max == 0) 0.U else (max - 1).U + when(cnt.value === expected) { stop() } } @@ -50,7 +52,9 @@ class RangeTester(r: Range) extends BasicTester { class CounterSpec extends ChiselPropSpec { property("Counter should count up") { - forAll(smallPosInts) { (max: Int) => assertTesterPasses{ new CountTester(max) } } + for (i <- 0 until 4) { + assertTesterPasses(new CountTester(i)) + } } property("Counter can be en/disabled") { -- cgit v1.2.3