From a2cb95bfe9e9c30b73284e97048fa0187ab0ee1d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 21 Sep 2016 12:44:36 -0700 Subject: Make implicit clock name consistent (#288) In the Chisel frontend, the implicit clock is named clock, but in the generated FIRRTL, it is named clk. There is no reason for this discrepancy, and yet fixing it is painful, as it will break test harnesses. Better to take the pain now than later. Resolves #258.--- src/main/resources/top.cpp | 8 ++++---- src/main/scala/chisel3/internal/firrtl/Emitter.scala | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/main/resources/top.cpp b/src/main/resources/top.cpp index 8bfe2a99..075d7085 100644 --- a/src/main/resources/top.cpp +++ b/src/main/resources/top.cpp @@ -44,10 +44,10 @@ int main(int argc, char** argv) { top->reset = 0; // Deassert reset } if ((main_time % 10) == 1) { - top->clk = 1; // Toggle clock + top->clock = 1; // Toggle clock } if ((main_time % 10) == 6) { - top->clk = 0; + top->clock = 0; } top->eval(); // Evaluate model #if VM_TRACE @@ -69,10 +69,10 @@ int main(int argc, char** argv) { vluint64_t end_time = main_time + 100; while (main_time < end_time) { if ((main_time % 10) == 1) { - top->clk = 1; // Toggle clock + top->clock = 1; // Toggle clock } if ((main_time % 10) == 6) { - top->clk = 0; + top->clock = 0; } top->eval(); // Evaluate model #if VM_TRACE diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala index 8849077d..f1908089 100644 --- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala +++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala @@ -24,10 +24,10 @@ private class Emitter(circuit: Circuit) { case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}" case e: Connect => s"${e.loc.fullName(ctx)} <= ${e.exp.fullName(ctx)}" case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}" - case e: Stop => s"stop(${e.clk.fullName(ctx)}, UInt<1>(1), ${e.ret})" + case e: Stop => s"stop(${e.clock.fullName(ctx)}, UInt<1>(1), ${e.ret})" case e: Printf => val (fmt, args) = e.pable.unpack(ctx) - val printfArgs = Seq(e.clk.fullName(ctx), "UInt<1>(1)", + val printfArgs = Seq(e.clock.fullName(ctx), "UInt<1>(1)", "\"" + printf.format(fmt) + "\"") ++ args printfArgs mkString ("printf(", ", ", ")") case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid" -- cgit v1.2.3 From b18e98ba2d058c7dd24f96f005486b70c856aeca Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 21 Sep 2016 16:16:25 -0700 Subject: Expose FIRRTL asClock construct Additionally, fix Clock.asUInt (previously, it threw an esoteric exception), and add a simple test of both.--- src/test/scala/chiselTests/Clock.scala | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/scala/chiselTests/Clock.scala (limited to 'src') diff --git a/src/test/scala/chiselTests/Clock.scala b/src/test/scala/chiselTests/Clock.scala new file mode 100644 index 00000000..79dd2de4 --- /dev/null +++ b/src/test/scala/chiselTests/Clock.scala @@ -0,0 +1,22 @@ +// See LICENSE for license details. + +package chiselTests + +import org.scalatest._ +import org.scalatest.prop._ + +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ + +class ClockAsUIntTester extends BasicTester { + assert(Bool(true).asClock.asUInt === UInt(1)) + stop() +} + + +class ClockSpec extends ChiselPropSpec { + property("Bool.asClock.asUInt should pass a signal through unaltered") { + assertTesterPasses { new ClockAsUIntTester } + } +} -- cgit v1.2.3 From 6eb00023fcc3ad77b98e51971f6e193ea506b9cc Mon Sep 17 00:00:00 2001 From: ducky Date: Wed, 21 Sep 2016 17:59:38 -0700 Subject: Improved scaladoc in utils and friends --- src/main/scala/chisel3/util/Cat.scala | 13 ++++--- src/main/scala/chisel3/util/CircuitMath.scala | 14 ++++---- src/main/scala/chisel3/util/Conditional.scala | 50 +++++++++++++++++++-------- src/main/scala/chisel3/util/Counter.scala | 25 +++++++++++--- src/main/scala/chisel3/util/OneHot.scala | 24 +++++++------ src/main/scala/chisel3/util/Reg.scala | 38 +++++++++++--------- 6 files changed, 105 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala index 469bf9ab..ba12a7d4 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -6,16 +6,15 @@ import chisel3._ import chisel3.core.SeqUtils object Cat { - /** Combine data elements together - * @param a Data to combine with - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together + /** Concatenates the argument data elements, in argument order, together. */ def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) - /** Combine data elements together - * @param r any number of other Data elements to be combined in order - * @return A UInt which is all of the bits combined together + /** Concatenates the data elements of the input sequence, in reverse sequence order, together. + * The first element of the sequence forms the most significant bits, while the last element + * in the sequence forms the least significant bits. + * + * Equivalent to r(0) ## r(1) ## ... ## r(n-1). */ def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) } diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index a64447d9..d478e10e 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -7,13 +7,11 @@ package chisel3.util import chisel3._ -/** Compute the base-2 integer logarithm of a UInt - * @example - * {{{ data_out := Log2(data_in) }}} - * @note The result is truncated, so e.g. Log2(UInt(13)) = 3 - */ object Log2 { - /** Compute the Log2 on the least significant n bits of x */ + /** Returns the base-2 integer logarithm of the least-significant `width` bits of an UInt. + * + * @note The result is truncated, so e.g. Log2(UInt(13)) === UInt(3) + */ def apply(x: Bits, width: Int): UInt = { if (width < 2) { UInt(0) @@ -30,6 +28,10 @@ object Log2 { } } + /** Returns the base-2 integer logarithm of an UInt. + * + * @note The result is truncated, so e.g. Log2(UInt(13)) === UInt(3) + */ def apply(x: Bits): UInt = apply(x, x.getWidth) private def divideAndConquerThreshold = 4 diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 6218feb0..461ff765 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -12,50 +12,72 @@ import scala.reflect.macros.blackbox._ import chisel3._ -/** This is identical to [[Chisel.when when]] with the condition inverted */ object unless { // scalastyle:ignore object.name + /** Does the same thing as [[when$ when]], but with the condition inverted. + */ def apply(c: Bool)(block: => Unit) { when (!c) { block } } } +/** Implementation details for [[switch]]. See [[switch]] and [[chisel3.util.is is]] for the + * user-facing API. + */ class SwitchContext[T <: Bits](cond: T) { def is(v: Iterable[T])(block: => Unit) { - if (!v.isEmpty) when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { block } + if (!v.isEmpty) { + when (v.map(_.asUInt === cond.asUInt).reduce(_||_)) { + block + } + } } def is(v: T)(block: => Unit) { is(Seq(v))(block) } def is(v: T, vr: T*)(block: => Unit) { is(v :: vr.toList)(block) } } -/** An object for separate cases in [[Chisel.switch switch]] - * It is equivalent to a [[Chisel.when$ when]] block comparing to the condition - * Use outside of a switch statement is illegal */ +/** Use to specify cases in a [[switch]] block, equivalent to a [[when$ when]] block comparing to + * the condition variable. + * + * @note illegal outside a [[switch]] block + * @note multiple conditions may fire simultaneously + * @note dummy implementation, a macro inside [[switch]] transforms this into the actual + * implementation + */ object is { // scalastyle:ignore object.name - // Begin deprecation of non-type-parameterized is statements. + // TODO: Begin deprecation of non-type-parameterized is statements. + /** Executes `block` if the switch condition is equal to any of the values in `v`. + */ def apply(v: Iterable[Bits])(block: => Unit) { require(false, "The 'is' keyword may not be used outside of a switch.") } + /** Executes `block` if the switch condition is equal to `v`. + */ def apply(v: Bits)(block: => Unit) { require(false, "The 'is' keyword may not be used outside of a switch.") } + /** Executes `block` if the switch condition is equal to any of the values in the argument list. + */ def apply(v: Bits, vr: Bits*)(block: => Unit) { require(false, "The 'is' keyword may not be used outside of a switch.") } } -/** Conditional logic to form a switch block +/** Conditional logic to form a switch block. See [[is$ is]] for the case API. + * * @example - * {{{ ... // default values here - * switch ( myState ) { - * is( state1 ) { - * ... // some logic here + * {{{ + * switch (myState) { + * is (state1) { + * // some logic here that runs when myState === state1 * } - * is( state2 ) { - * ... // some logic here + * is (state2) { + * // some logic here that runs when myState === state2 * } - * } }}}*/ + * } + * }}} + */ object switch { // scalastyle:ignore object.name def apply[T <: Bits](cond: T)(x: => Unit): Unit = macro impl def impl(c: Context)(cond: c.Tree)(x: c.Tree): c.Tree = { import c.universe._ diff --git a/src/main/scala/chisel3/util/Counter.scala b/src/main/scala/chisel3/util/Counter.scala index 1c95190b..4b20158f 100644 --- a/src/main/scala/chisel3/util/Counter.scala +++ b/src/main/scala/chisel3/util/Counter.scala @@ -5,12 +5,14 @@ package chisel3.util import chisel3._ /** A counter module + * * @param n number of counts before the counter resets (or one more than the * maximum output value of the counter), need not be a power of two */ class Counter(val n: Int) { require(n >= 0) val value = if (n > 1) Reg(init=UInt(0, log2Up(n))) else UInt(0) + /** Increment the counter, returning whether the counter currently is at the * maximum and will wrap. The incremented value is registered and will be * visible on the next cycle. @@ -29,14 +31,27 @@ class Counter(val n: Int) { } } -/** Counter Object - * Example Usage: - * {{{ val countOn = Bool(true) // increment counter every clock cycle - * val (myCounterValue, myCounterWrap) = Counter(countOn, n) - * when ( myCounterValue === UInt(3) ) { ... } }}}*/ object Counter { + /** Instantiate a [[Counter! counter]] with the specified number of counts. + */ def apply(n: Int): Counter = new Counter(n) + + /** Instantiate a [[Counter! counter]] with the specified number of counts and a gate. + * + * @param cond condition that controls whether the counter increments this cycle + * @param n number of counts before the counter resets + * @return tuple of the counter value and whether the counter will wrap (the value is at + * maximum and the condition is true). + * + * @example {{{ + * val countOn = Bool(true) // increment counter every clock cycle + * val (counterValue, counterWrap) = Counter(countOn, 4) + * when (counterValue === UInt(3)) { + * ... + * } + * }}} + */ def apply(cond: Bool, n: Int): (UInt, Bool) = { val c = new Counter(n) var wrap: Bool = null diff --git a/src/main/scala/chisel3/util/OneHot.scala b/src/main/scala/chisel3/util/OneHot.scala index 7e04a8d7..53ba8c3d 100644 --- a/src/main/scala/chisel3/util/OneHot.scala +++ b/src/main/scala/chisel3/util/OneHot.scala @@ -7,8 +7,12 @@ package chisel3.util import chisel3._ -/** Converts from One Hot Encoding to a UInt indicating which bit is active - * This is the inverse of [[Chisel.UIntToOH UIntToOH]]*/ +/** Returns the bit position of the sole high bit of the input bitvector. + * + * Inverse operation of [[UIntToOH]]. + * + * @note assumes exactly one high bit, results undefined otherwise + */ object OHToUInt { def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size) def apply(in: Vec[Bool]): UInt = apply(in.asUInt, in.size) @@ -26,9 +30,9 @@ object OHToUInt { } } -/** @return the bit position of the trailing 1 in the input vector - * with the assumption that multiple bits of the input bit vector can be set - * @example {{{ data_out := PriorityEncoder(data_in) }}} +/** Returns the bit position of the least-significant high bit of the input bitvector. + * + * Multiple bits may be high in the input. */ object PriorityEncoder { def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(UInt(_))) @@ -37,8 +41,7 @@ object PriorityEncoder { /** Returns the one hot encoding of the input UInt. */ -object UIntToOH -{ +object UIntToOH { def apply(in: UInt, width: Int = -1): UInt = if (width == -1) { UInt(1) << in @@ -47,11 +50,10 @@ object UIntToOH } } -/** Returns a bit vector in which only the least-significant 1 bit in - the input vector, if any, is set. +/** Returns a bit vector in which only the least-significant 1 bit in the input vector, if any, + * is set. */ -object PriorityEncoderOH -{ +object PriorityEncoderOH { private def encode(in: Seq[Bool]): UInt = { val outs = Seq.tabulate(in.size)(i => UInt(BigInt(1) << i, in.size)) PriorityMux(in :+ Bool(true), outs :+ UInt(0, in.size)) diff --git a/src/main/scala/chisel3/util/Reg.scala b/src/main/scala/chisel3/util/Reg.scala index 81de4754..80a3f43e 100644 --- a/src/main/scala/chisel3/util/Reg.scala +++ b/src/main/scala/chisel3/util/Reg.scala @@ -1,34 +1,40 @@ // See LICENSE for license details. -/** Variations and helpers for registers. - */ - package chisel3.util import chisel3._ object RegNext { - + /** Returns a register with the specified next and no reset initialization. + * + * Essentially a 1-cycle delayed version of the input signal. + */ def apply[T <: Data](next: T): T = Reg[T](null.asInstanceOf[T], next, null.asInstanceOf[T]) + /** Returns a register with the specified next and reset initialization. + * + * Essentially a 1-cycle delayed version of the input signal. + */ def apply[T <: Data](next: T, init: T): T = Reg[T](null.asInstanceOf[T], next, init) - } object RegInit { - + /** Returns a register pre-initialized (on reset) to the specified value. + */ def apply[T <: Data](init: T): T = Reg[T](null.asInstanceOf[T], null.asInstanceOf[T], init) - } -/** A register with an Enable signal */ -object RegEnable -{ +object RegEnable { + /** Returns a register with the specified next, update enable gate, and no reset initialization. + */ def apply[T <: Data](updateData: T, enable: Bool): T = { val r = Reg(updateData) when (enable) { r := updateData } r } + + /** Returns a register with the specified next, update enable gate, and reset initialization. + */ def apply[T <: Data](updateData: T, resetData: T, enable: Bool): T = { val r = RegInit(resetData) when (enable) { r := updateData } @@ -36,15 +42,15 @@ object RegEnable } } -/** Returns the n-cycle delayed version of the input signal. - */ object ShiftRegister { - /** @param in input to delay + /** Returns the n-cycle delayed version of the input signal. + * + * @param in input to delay * @param n number of cycles to delay - * @param en enable the shift */ - def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = - { + * @param en enable the shift + */ + def apply[T <: Data](in: T, n: Int, en: Bool = Bool(true)): T = { // The order of tests reflects the expected use cases. if (n == 1) { RegEnable(in, en) -- cgit v1.2.3 From decb2ee0f0bb8223f0b2b067b88ed90b71473a28 Mon Sep 17 00:00:00 2001 From: ducky Date: Thu, 22 Sep 2016 15:21:48 -0700 Subject: Update rest of docs --- src/main/scala/chisel3/util/Arbiter.scala | 45 ++++++++++++++++----------- src/main/scala/chisel3/util/BitPat.scala | 2 +- src/main/scala/chisel3/util/Bitwise.scala | 26 +++++++++++----- src/main/scala/chisel3/util/Conditional.scala | 5 ++- src/main/scala/chisel3/util/Decoupled.scala | 42 ++++++++++++++----------- src/main/scala/chisel3/util/Enum.scala | 36 +++++++++++++++++++-- src/main/scala/chisel3/util/LFSR.scala | 13 ++++---- src/main/scala/chisel3/util/Mux.scala | 23 +++++++------- 8 files changed, 123 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/main/scala/chisel3/util/Arbiter.scala b/src/main/scala/chisel3/util/Arbiter.scala index eb541977..58ba1188 100644 --- a/src/main/scala/chisel3/util/Arbiter.scala +++ b/src/main/scala/chisel3/util/Arbiter.scala @@ -7,16 +7,21 @@ package chisel3.util import chisel3._ -/** An I/O bundle for the Arbiter */ +/** IO bundle definition for an Arbiter, which takes some number of ready-valid inputs and outputs + * (selects) at most one. + * + * @param gen data type + * @param n number of inputs + */ class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle { val in = Vec(n, Decoupled(gen)).flip val out = Decoupled(gen) val chosen = UInt(OUTPUT, log2Up(n)) } -/** Arbiter Control determining which producer has access */ -private object ArbiterCtrl -{ +/** Arbiter Control determining which producer has access + */ +private object ArbiterCtrl { def apply(request: Seq[Bool]): Seq[Bool] = request.length match { case 0 => Seq() case 1 => Seq(Bool(true)) @@ -81,25 +86,27 @@ class LockingArbiter[T <: Data](gen: T, n: Int, count: Int, needsLock: Option[T } /** Hardware module that is used to sequence n producers into 1 consumer. - Producers are chosen in round robin order. - - Example usage: - val arb = new RRArbiter(2, UInt()) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out + * Producers are chosen in round robin order. + * + * @example {{{ + * val arb = new RRArbiter(2, UInt()) + * arb.io.in(0) <> producer0.io.out + * arb.io.in(1) <> producer1.io.out + * consumer.io.in <> arb.io.out + * }}} */ class RRArbiter[T <: Data](gen:T, n: Int) extends LockingRRArbiter[T](gen, n, 1) /** Hardware module that is used to sequence n producers into 1 consumer. - Priority is given to lower producer - - Example usage: - val arb = Module(new Arbiter(2, UInt())) - arb.io.in(0) <> producer0.io.out - arb.io.in(1) <> producer1.io.out - consumer.io.in <> arb.io.out - */ + * Priority is given to lower producer. + * + * @example {{{ + * val arb = Module(new Arbiter(2, UInt())) + * arb.io.in(0) <> producer0.io.out + * arb.io.in(1) <> producer1.io.out + * consumer.io.in <> arb.io.out + * }}} + */ class Arbiter[T <: Data](gen: T, n: Int) extends Module { val io = new ArbiterIO(gen, n) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 26106080..6c012583 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -37,7 +37,7 @@ object BitPat { /** Creates a [[BitPat]] literal from a string. * * @param n the literal value as a string, in binary, prefixed with 'b' - * @note legal characters are '0', '1', and '?', as well as '_' as white + * @note legal characters are '0', '1', and '?', as well as '_' and white * space (which are ignored) */ def apply(n: String): BitPat = { diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index 6451ab14..7d5ffe09 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -8,9 +8,18 @@ package chisel3.util import chisel3._ import chisel3.core.SeqUtils -object FillInterleaved -{ +object FillInterleaved { + /** Creates n repetitions of each bit of x in order. + * + * Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times) + * For example, FillInterleaved(2, "b1000") === UInt("b11 00 00 00") + */ def apply(n: Int, in: UInt): UInt = apply(n, in.toBools) + + /** Creates n repetitions of each bit of x in order. + * + * Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times) + */ def apply(n: Int, in: Seq[Bool]): UInt = Cat(in.map(Fill(n, _)).reverse) } @@ -22,9 +31,11 @@ object PopCount def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) } -/** Fill fans out a UInt to multiple copies */ object Fill { - /** Fan out x n times */ + /** Create n repetitions of x using a tree fanout topology. + * + * Output data-equivalent to x ## x ## ... ## x (n repetitions). + */ def apply(n: Int, x: UInt): UInt = { n match { case 0 => UInt(width=0) @@ -42,10 +53,7 @@ object Fill { } } -/** Litte/big bit endian convertion: reverse the order of the bits in a UInt. -*/ -object Reverse -{ +object Reverse { private def doit(in: UInt, length: Int): UInt = { if (length == 1) { in @@ -65,5 +73,7 @@ object Reverse Cat(doit(in(half-1,0), half), doit(in(length-1,half), length-half)) } } + /** Returns the input in bit-reversed order. Useful for little/big-endian conversion. + */ def apply(in: UInt): UInt = doit(in, in.getWidth) } diff --git a/src/main/scala/chisel3/util/Conditional.scala b/src/main/scala/chisel3/util/Conditional.scala index 461ff765..5830e014 100644 --- a/src/main/scala/chisel3/util/Conditional.scala +++ b/src/main/scala/chisel3/util/Conditional.scala @@ -65,9 +65,8 @@ object is { // scalastyle:ignore object.name } /** Conditional logic to form a switch block. See [[is$ is]] for the case API. - * - * @example - * {{{ + * + * @example {{{ * switch (myState) { * is (state1) { * // some logic here that runs when myState === state1 diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 77990777..65558aa9 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -21,10 +21,10 @@ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle def fire(dummy: Int = 0): Bool = ready && valid } -/** A concrete subclass of ReadyValidIO signalling that the user expects a +/** A concrete subclass of ReadyValidIO signaling that the user expects a * "decoupled" interface: 'valid' indicates that the producer has * put valid data in 'bits', and 'ready' indicates that the consumer is ready - * to accept the data this cycle. No requirements are placed on the signalling + * to accept the data this cycle. No requirements are placed on the signaling * of ready or valid. */ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) @@ -35,12 +35,12 @@ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) /** This factory adds a decoupled handshaking protocol to a data bundle. */ object Decoupled { - /** Take any Data and wrap it in a DecoupledIO interface */ + /** Wraps some Data with a DecoupledIO interface. */ def apply[T <: Data](gen: T): DecoupledIO[T] = new DecoupledIO(gen) - /** Take an IrrevocableIO and cast it to a DecoupledIO. - * This cast is only safe to do in cases where the IrrevocableIO - * is being produced as an output. + /** Downconverts an IrrevocableIO output to a DecoupledIO, dropping guarantees of irrevocability. + * + * @note unsafe (and will error) on the producer (input) side of an IrrevocableIO */ def apply[T <: Data](irr: IrrevocableIO[T]): DecoupledIO[T] = { require(irr.bits.dir == OUTPUT, "Only safe to cast produced Irrevocable bits to Decoupled.") @@ -67,9 +67,10 @@ object Irrevocable { def apply[T <: Data](gen: T): IrrevocableIO[T] = new IrrevocableIO(gen) - /** Take a DecoupledIO and cast it to an IrrevocableIO. - * This cast is only safe to do in cases where the IrrevocableIO - * is being consumed as an input. + /** Upconverts a DecoupledIO input to an IrrevocableIO, allowing an IrrevocableIO to be used + * where a DecoupledIO is expected. + * + * @note unsafe (and will error) on the consumer (output) side of an DecoupledIO */ def apply[T <: Data](dec: DecoupledIO[T]): IrrevocableIO[T] = { require(dec.bits.dir == INPUT, "Only safe to cast consumed Decoupled bits to Irrevocable.") @@ -156,10 +157,11 @@ class QueueIO[T <: Data](gen: T, entries: Int) extends Bundle * @param flow True if the inputs can be consumed on the same cycle (the inputs "flow" through the queue immediately). * The ''valid'' signals are coupled. * - * Example usage: - * {{{ val q = new Queue(UInt(), 16) - * q.io.enq <> producer.io.out - * consumer.io.in <> q.io.deq }}} + * @example {{{ + * val q = new Queue(UInt(), 16) + * q.io.enq <> producer.io.out + * consumer.io.in <> q.io.deq + * }}} */ class Queue[T <: Data](gen: T, val entries: Int, @@ -223,12 +225,16 @@ extends Module(override_reset=override_reset) { } } -/** Factory for a generic hardware queue. Required parameter 'entries' controls - * the depth of the queues. The width of the queue is determined - * from the input 'enq'. +/** Factory for a generic hardware queue. * - * Example usage: - * {{{ consumer.io.in <> Queue(producer.io.out, 16) }}} + * @param enq input (enqueue) interface to the queue, also determines width of queue elements + * @param entries depth (number of elements) of the queue + * + * @returns output (dequeue) interface from the queue + * + * @example {{{ + * consumer.io.in <> Queue(producer.io.out, 16) + * }}} */ object Queue { diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index 4ecc243b..55b595ee 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -12,12 +12,42 @@ object Enum { private def createValues[T <: Bits](nodeType: T, n: Int): Seq[T] = (0 until n).map(x => nodeType.fromInt(x, log2Up(n))) - /** create n enum values of given type */ + /** Returns n unique values of the specified type. Can be used with unpacking to define enums. + * + * @example {{{ + * val state_on :: state_off :: Nil = Enum(UInt(), 2) + * val current_state = UInt() + * switch (current_state) { + * is (state_on) { + * ... + * } + * if (state_off) { + * ... + * } + * } + * }}} + * + */ def apply[T <: Bits](nodeType: T, n: Int): List[T] = createValues(nodeType, n).toList - /** create enum values of given type and names */ + /** Returns a map of the input symbols to unique values of the specified type. + * + * @example {{{ + * val states = Enum(UInt(), 'on, 'off) + * val current_state = UInt() + * switch (current_state) { + * is (states('on)) { + * ... + * } + * if (states('off)) { + * .. + * } + * } + * }}} + */ def apply[T <: Bits](nodeType: T, l: Symbol *): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap - /** create enum values of given type and names */ + /** Returns a map of the input symbols to unique values of the specified type. + */ def apply[T <: Bits](nodeType: T, l: List[Symbol]): Map[Symbol, T] = (l zip createValues(nodeType, l.length)).toMap } diff --git a/src/main/scala/chisel3/util/LFSR.scala b/src/main/scala/chisel3/util/LFSR.scala index a30c276f..e4261c20 100644 --- a/src/main/scala/chisel3/util/LFSR.scala +++ b/src/main/scala/chisel3/util/LFSR.scala @@ -8,12 +8,13 @@ package chisel3.util import chisel3._ // scalastyle:off magic.number -/** linear feedback shift register - */ -object LFSR16 -{ - def apply(increment: Bool = Bool(true)): UInt = - { +object LFSR16 { + /** Generates a 16-bit linear feedback shift register, returning the register contents. + * May be useful for generating a pseudorandom sequence. + * + * @param increment optional control to gate when the LFSR updates. + */ + def apply(increment: Bool = Bool(true)): UInt = { val width = 16 val lfsr = Reg(init=UInt(1, width)) when (increment) { lfsr := Cat(lfsr(0)^lfsr(2)^lfsr(3)^lfsr(5), lfsr(width-1,1)) } diff --git a/src/main/scala/chisel3/util/Mux.scala b/src/main/scala/chisel3/util/Mux.scala index 9956a7e3..245de67e 100644 --- a/src/main/scala/chisel3/util/Mux.scala +++ b/src/main/scala/chisel3/util/Mux.scala @@ -9,10 +9,11 @@ import chisel3._ import chisel3.core.SeqUtils /** Builds a Mux tree out of the input signal vector using a one hot encoded - select signal. Returns the output of the Mux tree. + * select signal. Returns the output of the Mux tree. + * + * @note results undefined if multiple select signals are simultaneously high */ -object Mux1H -{ +object Mux1H { def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) def apply[T <: Data](in: Iterable[(Bool, T)]): T = SeqUtils.oneHotMux(in) @@ -22,18 +23,17 @@ object Mux1H } /** Builds a Mux tree under the assumption that multiple select signals - can be enabled. Priority is given to the first select signal. - - Returns the output of the Mux tree. + * can be enabled. Priority is given to the first select signal. + * + * Returns the output of the Mux tree. */ -object PriorityMux -{ +object PriorityMux { def apply[T <: Data](in: Seq[(Bool, T)]): T = SeqUtils.priorityMux(in) def apply[T <: Data](sel: Seq[Bool], in: Seq[T]): T = apply(sel zip in) def apply[T <: Data](sel: Bits, in: Seq[T]): T = apply((0 until in.size).map(sel(_)), in) } -/** MuxLookup creates a cascade of n Muxs to search for a key value */ +/** Creates a cascade of n Muxs to search for a key value. */ object MuxLookup { /** @param key a key to search for * @param default a default value if nothing is found @@ -46,10 +46,11 @@ object MuxLookup { res = Mux(k === key, v, res) res } - } -/** MuxCase returns the first value that is enabled in a map of values */ +/** Given an association of values to enable signals, returns the first value with an associated + * high enable signal. + */ object MuxCase { /** @param default the default value if none are enabled * @param mapping a set of data values with associated enables -- cgit v1.2.3