diff options
| author | Jim Lawson | 2016-12-19 10:20:48 -0800 |
|---|---|---|
| committer | GitHub | 2016-12-19 10:20:48 -0800 |
| commit | dd4650d29ed18ec610ad7561f4e9c990ba887a3d (patch) | |
| tree | 333fe66fba7ea7337fa1f6ffe1ec905cd2f724f3 /src | |
| parent | 207da69768dac464a719a7c712f6977371f7c5f4 (diff) | |
| parent | 0233f704e83d380b1fe8311dfffa3f44f74b506b (diff) | |
Merge branch 'master' into exceptionfix
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/chisel3/Driver.scala | 20 | ||||
| -rw-r--r-- | src/main/scala/chisel3/package.scala | 3 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/BitPat.scala | 19 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Bitwise.scala | 46 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Cat.scala | 13 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/CircuitMath.scala | 17 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 5 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AnnotatingDiamondSpec.scala | 163 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AnnotatingExample.scala | 145 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AnnotationNoDedup.scala | 78 | ||||
| -rw-r--r-- | src/test/scala/cookbook/FSM.scala | 61 | ||||
| -rw-r--r-- | src/test/scala/cookbook/RegOfVec.scala | 33 |
12 files changed, 438 insertions, 165 deletions
diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index ab51ad25..40c94b54 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -6,10 +6,13 @@ import chisel3.internal.firrtl.Emitter import scala.sys.process._ import java.io._ +import net.jcazevedo.moultingyaml._ import internal.firrtl._ import firrtl._ +import _root_.firrtl.annotations.AnnotationYamlProtocol._ + /** * The Driver provides methods to invoke the chisel3 compiler and the firrtl compiler. * By default firrtl is automatically run after chisel. an [[ExecutionOptionsManager]] @@ -239,6 +242,23 @@ object Driver extends BackendCompilationUtilities { w.write(firrtlString) w.close() + val annotationFile = new File(optionsManager.getBuildFileName("anno")) + val af = new FileWriter(annotationFile) + af.write(circuit.annotations.toArray.toYaml.prettyPrint) + af.close() + + /* create custom transforms by finding the set of transform classes associated with annotations + * then instantiate them into actual transforms + */ + val transforms = circuit.annotations.map(_.transform).toSet.map { transformClass: Class[_ <: Transform] => + transformClass.newInstance() + } + /* This passes the firrtl source and annotations directly to firrtl */ + optionsManager.firrtlOptions = optionsManager.firrtlOptions.copy( + firrtlSource = Some(firrtlString), + annotations = circuit.annotations.toList, + customTransforms = transforms.toList) + val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) { Some(firrtl.Driver.execute(optionsManager)) } diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index e4e64b89..25d3ec3a 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -32,6 +32,9 @@ package object chisel3 { // scalastyle:ignore package.object.name type Element = chisel3.core.Element type Bits = chisel3.core.Bits + type ChiselAnnotation = chisel3.core.ChiselAnnotation + val ChiselAnnotation = chisel3.core.ChiselAnnotation + // Some possible regex replacements for the literal specifier deprecation: // (note: these are not guaranteed to handle all edge cases! check all replacements!) // Bool\((true|false)\) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 9c9909cd..add40f79 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -35,7 +35,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 '_' and white * space (which are ignored) @@ -45,7 +45,12 @@ object BitPat { new BitPat(bits, mask, width) } - /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. */ + /** Creates a [[BitPat]] of all don't cares of the specified bitwidth. + * + * @example {{{ + * val myDontCare = BitPat.dontCare(4) // equivalent to BitPat("b????") + * }}} + */ def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) @deprecated("Use BitPat.dontCare", "chisel3") @@ -73,10 +78,14 @@ object BitPat { } } -// TODO: Break out of Core? (this doesn't involve FIRRTL generation) /** Bit patterns are literals with masks, used to represent values with don't - * cares. Equality comparisons will ignore don't care bits (for example, - * BitPat(0b10?1) === 0b1001.asUInt and 0b1011.asUInt. + * care bits. Equality comparisons will ignore don't care bits. + * + * @example {{{ + * "b10101".U === BitPat("b101??") // evaluates to true.B + * "b10111".U === BitPat("b101??") // evaluates to true.B + * "b10001".U === BitPat("b101??") // evaluates to false.B + * }}} */ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { def getWidth: Int = width diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala index 22326972..950fa65f 100644 --- a/src/main/scala/chisel3/util/Bitwise.scala +++ b/src/main/scala/chisel3/util/Bitwise.scala @@ -8,11 +8,21 @@ package chisel3.util import chisel3._ import chisel3.core.SeqUtils +/** Creates repetitions of each bit of the input in order. + * + * @example {{{ + * FillInterleaved(2, "b1 0 0 0".U) // equivalent to "b11 00 00 00".U + * FillInterleaved(2, "b1 0 0 1".U) // equivalent to "b11 00 00 11".U + * FillInterleaved(2, myUIntWire) // dynamic interleaved fill + * + * FillInterleaved(2, Seq(true.B, false.B, false.B, false.B)) // equivalent to "b11 00 00 00".U + * FillInterleaved(2, Seq(true.B, false.B, false.B, true.B)) // equivalent to "b11 00 00 11".U + * }}} + */ 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) @@ -23,14 +33,31 @@ object FillInterleaved { 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. +/** Returns the number of bits set (value is 1 or true) in the input signal. + * + * @example {{{ + * PopCount(Seq(true.B, false.B, true.B, true.B)) // evaluates to 3.U + * PopCount(Seq(false.B, false.B, true.B, false.B)) // evaluates to 1.U + * + * PopCount("b1011".U) // evaluates to 3.U + * PopCount("b0010".U) // evaluates to 1.U + * PopCount(myUIntWire) // dynamic count + * }}} */ -object PopCount -{ +object PopCount { def apply(in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq) + def apply(in: Bits): UInt = apply((0 until in.getWidth).map(in(_))) } +/** Create repetitions of the input using a tree fanout topology. + * + * @example {{{ + * Fill(2, "b1000".U) // equivalent to "b1000 1000".U + * Fill(2, "b1001".U) // equivalent to "b1001 1001".U + * Fill(2, myUIntWire) // dynamic fill + * }}} + */ object Fill { /** Create n repetitions of x using a tree fanout topology. * @@ -53,6 +80,14 @@ object Fill { } } +/** Returns the input in bit-reversed order. Useful for little/big-endian conversion. + * + * @example {{{ + * Reverse("b1101".U) // equivalent to "b1011".U + * Reverse("b1101".U(8.W)) // equivalent to "b10110000".U + * Reverse(myUIntWire) // dynamic reverse + * }}} + */ object Reverse { private def doit(in: UInt, length: Int): UInt = { if (length == 1) { @@ -73,7 +108,6 @@ 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/Cat.scala b/src/main/scala/chisel3/util/Cat.scala index ba12a7d4..78801541 100644 --- a/src/main/scala/chisel3/util/Cat.scala +++ b/src/main/scala/chisel3/util/Cat.scala @@ -5,8 +5,19 @@ package chisel3.util import chisel3._ import chisel3.core.SeqUtils +/** Concatenates elements of the input, in order, together. + * + * @example {{{ + * Cat("b101".U, "b11".U) // equivalent to "b101 11".U + * Cat(myUIntWire0, myUIntWire1) + * + * Cat(Seq("b101".U, "b11".U)) // equivalent to "b101 11".U + * Cat(mySeqOfBits) + * }}} + */ object Cat { - /** Concatenates the argument data elements, in argument order, together. + /** Concatenates the argument data elements, in argument order, together. The first argument + * forms the most significant bits, while the last argument forms the least significant bits. */ def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) diff --git a/src/main/scala/chisel3/util/CircuitMath.scala b/src/main/scala/chisel3/util/CircuitMath.scala index a422b5fe..b5f491ef 100644 --- a/src/main/scala/chisel3/util/CircuitMath.scala +++ b/src/main/scala/chisel3/util/CircuitMath.scala @@ -7,10 +7,19 @@ package chisel3.util import chisel3._ +/** Returns the base-2 integer logarithm of an UInt. + * + * @note The result is truncated, so e.g. Log2(13.U) === 3.U + * + * @example {{{ + * Log2(8.U) // evaluates to 3.U + * Log2(13.U) // evaluates to 3.U (truncation) + * Log2(myUIntWire) + * }}} + * + */ object Log2 { /** Returns the base-2 integer logarithm of the least-significant `width` bits of an UInt. - * - * @note The result is truncated, so e.g. Log2(13.U) === 3.U */ def apply(x: Bits, width: Int): UInt = { if (width < 2) { @@ -28,10 +37,6 @@ object Log2 { } } - /** Returns the base-2 integer logarithm of an UInt. - * - * @note The result is truncated, so e.g. Log2(13.U) === 3.U - */ def apply(x: Bits): UInt = apply(x, x.getWidth) private def divideAndConquerThreshold = 4 diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index fcda6943..4a97724a 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -37,12 +37,13 @@ object ReadyValidIO { dat } - /** Indicate no enqueue occurs. Valid is set to false, and all bits are set to zero. + /** Indicate no enqueue occurs. Valid is set to false, and bits are + * connected to an uninitialized wire */ def noenq(): Unit = { target.valid := false.B // We want the type from the following, not any existing binding. - target.bits := target.bits.cloneType.fromBits(0.asUInt) + target.bits := Wire(target.bits.cloneType) } /** Assert ready on this port and return the associated data bits. diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala new file mode 100644 index 00000000..ff9f8e67 --- /dev/null +++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala @@ -0,0 +1,163 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import chisel3.internal.InstanceId +import chisel3.testers.BasicTester +import firrtl.{CircuitForm, CircuitState, LowForm, Transform} +import firrtl.annotations.{Annotation, ModuleName, Named} +import org.scalatest._ + +//scalastyle:off magic.number +/** + * This and the Identity transform class are a highly schematic implementation of a + * library implementation of (i.e. code outside of firrtl itself) + */ +object IdentityAnnotation { + def apply(target: Named, value: String): Annotation = Annotation(target, classOf[IdentityTransform], value) + + def unapply(a: Annotation): Option[(Named, String)] = a match { + case Annotation(named, t, value) if t == classOf[IdentityTransform] => Some((named, value)) + case _ => None + } +} + +class IdentityTransform extends Transform { + override def inputForm: CircuitForm = LowForm + + override def outputForm: CircuitForm = LowForm + + override def execute(state: CircuitState): CircuitState = { + getMyAnnotations(state) match { + case Nil => state + case myAnnotations => + state + } + } +} + +trait IdentityAnnotator { + self: Module => + def identify(component: InstanceId, value: String): Unit = { + annotate(ChiselAnnotation(component, classOf[IdentityTransform], value)) + } +} +/** A diamond circuit Top instantiates A and B and both A and B instantiate C + * Illustrations of annotations of various components and modules in both + * relative and absolute cases + * + * This is currently not much of a test, read the printout to see what annotations look like + */ +/** + * This class has parameterizable widths, it will generate different hardware + * @param widthC io width + */ +class ModC(widthC: Int) extends Module with IdentityAnnotator { + val io = IO(new Bundle { + val in = Input(UInt(widthC.W)) + val out = Output(UInt(widthC.W)) + }) + io.out := io.in + + identify(this, s"ModC($widthC)") + + identify(io.out, s"ModC(ignore param)") +} + +/** + * instantiates a C of a particular size, ModA does not generate different hardware + * based on it's parameter + * @param annoParam parameter is only used in annotation not in circuit + */ +class ModA(annoParam: Int) extends Module with IdentityAnnotator { + val io = IO(new Bundle { + val in = Input(UInt()) + val out = Output(UInt()) + }) + val modC = Module(new ModC(16)) + modC.io.in := io.in + io.out := modC.io.out + + identify(this, s"ModA(ignore param)") + + identify(io.out, s"ModA.io.out($annoParam)") + identify(io.out, s"ModA.io.out(ignore_param)") +} + +class ModB(widthB: Int) extends Module with IdentityAnnotator{ + val io = IO(new Bundle { + val in = Input(UInt(widthB.W)) + val out = Output(UInt(widthB.W)) + }) + val modC = Module(new ModC(widthB)) + modC.io.in := io.in + io.out := modC.io.out + + identify(io.in, s"modB.io.in annotated from inside modB") +} + +class TopOfDiamond extends Module with IdentityAnnotator { + val io = IO(new Bundle { + val in = Input(UInt(32.W)) + val out = Output(UInt(32.W)) + }) + val x = Reg(UInt(32.W)) + val y = Reg(UInt(32.W)) + + val modA = Module(new ModA(64)) + val modB = Module(new ModB(32)) + + x := io.in + modA.io.in := x + modB.io.in := x + + y := modA.io.out + modB.io.out + io.out := y + + identify(this, s"TopOfDiamond\nWith\nSome new lines") + + identify(modB.io.in, s"modB.io.in annotated from outside modB") +} + +class DiamondTester extends BasicTester { + val dut = Module(new TopOfDiamond) + + stop() +} + +class AnnotatingDiamondSpec extends FreeSpec with Matchers { + def findAnno(as: Seq[Annotation], name: String): Option[Annotation] = { + as.find { a => a.targetString == name } + } + + """ + |Diamond is an example of a module that has two sub-modules A and B who both instantiate their + |own instances of module C. This highlights the difference between specific and general + |annotation scopes + """.stripMargin - { + + """ + |annotations are not resolved at after circuit elaboration, + |that happens only after emit has been called on circuit""".stripMargin in { + + Driver.execute(Array.empty[String], () => new TopOfDiamond) match { + case ChiselExecutionSucccess(Some(circuit), emitted, _) => + val annos = circuit.annotations + annos.length should be (10) + + annos.count { + case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC" && annoValue == "ModC(16)" + case _ => false + } should be (1) + + annos.count { + case Annotation(ModuleName(name, _), _, annoValue) => name == "ModC_1" && annoValue == "ModC(32)" + case _ => false + } should be (1) + case _ => + assert(false) + } + } + } +}
\ No newline at end of file diff --git a/src/test/scala/chiselTests/AnnotatingExample.scala b/src/test/scala/chiselTests/AnnotatingExample.scala deleted file mode 100644 index 0be3ba59..00000000 --- a/src/test/scala/chiselTests/AnnotatingExample.scala +++ /dev/null @@ -1,145 +0,0 @@ -// See LICENSE for license details. - -package chiselTests - -import chisel3._ -import chisel3.core.Module -import chisel3.internal.InstanceId -import chisel3.testers.BasicTester -import org.scalatest._ - -import scala.util.DynamicVariable - -//scalastyle:off magic.number - -/** - * This Spec file illustrates use of Donggyu's component name API, it currently only - * uses three methods .signalName, .parentModName and .pathName - * - * This is also an illustration of how to implement an annotation system in chisel3 - * A local (my) Driver and Builder are created to provide thread-local access to - * an annotation map, and then a post elaboration annotation processor can resolve - * the keys and could serialize the annotations to a file for use by firrtl passes - */ - -class SomeSubMod(param1: Int, param2: Int) extends Module { - val io = new Bundle { - val in = Input(UInt(16.W)) - val out = Output(SInt(32.W)) - } - val annotate = MyBuilder.myDynamicContext.annotationMap - - annotate(AnnotationKey(this, JustThisRef)) = s"SomeSubMod($param1, $param2)" - annotate(AnnotationKey(io.in, AllRefs)) = "sub mod io.in" - annotate(AnnotationKey(io.out, JustThisRef)) = "sub mod io.out" -} - -class AnnotatingExample extends Module { - val io = new Bundle { - val a = Input(UInt(32.W)) - val b = Input(UInt(32.W)) - val e = Input(Bool()) - val z = Output(UInt(32.W)) - val v = Output(Bool()) - val bun = new Bundle { - val nested_1 = Input(UInt(12.W)) - val nested_2 = Output(Bool()) - } - } - val x = Reg(UInt(32.W)) - val y = Reg(UInt(32.W)) - - val subModule1 = Module(new SomeSubMod(1, 2)) - val subModule2 = Module(new SomeSubMod(3, 4)) - - - val annotate = MyBuilder.myDynamicContext.annotationMap - - annotate(AnnotationKey(subModule2, AllRefs)) = s"SomeSubMod was used" - - annotate(AnnotationKey(x, JustThisRef)) = "I am register X" - annotate(AnnotationKey(y, AllRefs)) = "I am register Y" - annotate(AnnotationKey(io.a, JustThisRef)) = "I am io.a" - annotate(AnnotationKey(io.bun.nested_1, AllRefs)) = "I am io.bun.nested_1" - annotate(AnnotationKey(io.bun.nested_2, JustThisRef)) = "I am io.bun.nested_2" -} - -class AnnotatingExampleTester extends BasicTester { - val dut = Module(new AnnotatingExample) - - stop() -} - -class AnnotatingExampleSpec extends FlatSpec with Matchers { - behavior of "Annotating components of a circuit" - - it should "contain the following relative keys" in { - val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } - - annotationMap.contains("SomeSubMod.io.in") should be(true) - annotationMap.contains("AnnotatingExample.y") should be(true) - - annotationMap("SomeSubMod.io.in") should be("sub mod io.in") - } - it should "contain the following absolute keys" in { - val annotationMap = MyDriver.buildAnnotatedCircuit { () => new AnnotatingExampleTester } - - annotationMap.contains("AnnotatingExampleTester.dut.subModule2.io.out") should be (true) - annotationMap.contains("AnnotatingExampleTester.dut.x") should be (true) - - annotationMap("AnnotatingExampleTester.dut.subModule2.io.out") should be ("sub mod io.out") - } -} - -trait AnnotationScope -case object AllRefs extends AnnotationScope -case object JustThisRef extends AnnotationScope - -object AnnotationKey { - def apply(component: InstanceId): AnnotationKey = { - AnnotationKey(component, AllRefs) - } -} -case class AnnotationKey(val component: InstanceId, scope: AnnotationScope) { - override def toString: String = { - scope match { - case JustThisRef => - s"${component.pathName}" - case AllRefs => - s"${component.parentModName}.${component.instanceName}" - case _ => - s"${component.toString}_unknown_scope" - } - } -} - -class AnnotationMap extends scala.collection.mutable.HashMap[AnnotationKey, String] - -class MyDynamicContext { - val annotationMap = new AnnotationMap -} - -object MyBuilder { - private val myDynamicContextVar = new DynamicVariable[Option[MyDynamicContext]](None) - - def myDynamicContext: MyDynamicContext = - myDynamicContextVar.value getOrElse new MyDynamicContext - - def processAnnotations(annotationMap: AnnotationMap): Map[String, String] = { - annotationMap.map { case (k,v) => k.toString -> v}.toMap - } - - def build[T <: Module](f: => T): Map[String, String] = { - myDynamicContextVar.withValue(Some(new MyDynamicContext)) { - Driver.emit(() => f) - processAnnotations(myDynamicContextVar.value.get.annotationMap) - } - } -} - -object MyDriver extends BackendCompilationUtilities { - /** - * illustrates a chisel3 style driver that, annotations can only processed within this structure - */ - def buildAnnotatedCircuit[T <: Module](gen: () => T): Map[String, String] = MyBuilder.build(gen()) -} diff --git a/src/test/scala/chiselTests/AnnotationNoDedup.scala b/src/test/scala/chiselTests/AnnotationNoDedup.scala new file mode 100644 index 00000000..024b5a7a --- /dev/null +++ b/src/test/scala/chiselTests/AnnotationNoDedup.scala @@ -0,0 +1,78 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ +import firrtl.FirrtlExecutionSuccess +import firrtl.transforms.DedupModules +import org.scalatest.{FreeSpec, Matchers} + +trait NoDedupAnnotator { + self: Module => + + def doNotDedup(module: Module): Unit = { + annotate(ChiselAnnotation(module, classOf[DedupModules], "nodedup!")) + } +} + +class MuchUsedModule extends Module { + val io = IO(new Bundle { + val in = Input(UInt(16.W)) + val out = Output(UInt(16.W)) + }) + io.out := io.in +% 1.U +} + +class UsesMuchUsedModule(addAnnos: Boolean) extends Module with NoDedupAnnotator{ + val io = IO(new Bundle { + val in = Input(UInt(16.W)) + val out = Output(UInt(16.W)) + }) + + val mod0 = Module(new MuchUsedModule) + val mod1 = Module(new MuchUsedModule) + val mod2 = Module(new MuchUsedModule) + val mod3 = Module(new MuchUsedModule) + + mod0.io.in := io.in + mod1.io.in := mod0.io.out + mod2.io.in := mod1.io.out + mod3.io.in := mod2.io.out + io.out := mod3.io.out + + if(addAnnos) { + doNotDedup(mod1) + doNotDedup(mod3) + } +} + +class AnnotationNoDedup extends FreeSpec with Matchers { + "Firrtl provides transform that reduces identical modules to a single instance" - { + "Annotations can be added which will defeat this deduplication for specific modules instances" in { + Driver.execute(Array("-X", "low"), () => new UsesMuchUsedModule(addAnnos = true)) match { + case ChiselExecutionSucccess(_, _, Some(firrtlResult: FirrtlExecutionSuccess)) => + val lowFirrtl = firrtlResult.emitted + + lowFirrtl should include ("module MuchUsedModule :") + lowFirrtl should include ("module MuchUsedModule_1 :") + lowFirrtl should include ("module MuchUsedModule_3 :") + lowFirrtl should not include "module MuchUsedModule_2 :" + lowFirrtl should not include "module MuchUsedModule_4 :" + case _ => + } + } + "Turning off these nnotations dedup all the occurrences" in { + Driver.execute(Array("-X", "low"), () => new UsesMuchUsedModule(addAnnos = false)) match { + case ChiselExecutionSucccess(_, _, Some(firrtlResult: FirrtlExecutionSuccess)) => + val lowFirrtl = firrtlResult.emitted + + lowFirrtl should include ("module MuchUsedModule :") + lowFirrtl should not include "module MuchUsedModule_1 :" + lowFirrtl should not include "module MuchUsedModule_3 :" + lowFirrtl should not include "module MuchUsedModule_2 :" + lowFirrtl should not include "module MuchUsedModule_4 :" + case _ => + } + } + } +} diff --git a/src/test/scala/cookbook/FSM.scala b/src/test/scala/cookbook/FSM.scala new file mode 100644 index 00000000..58f6a9a2 --- /dev/null +++ b/src/test/scala/cookbook/FSM.scala @@ -0,0 +1,61 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ +import chisel3.util._ + +/* ### How do I create a finite state machine? + + * Use Chisel Enum to construct the states and switch & is to construct the FSM + * control logic + */ +class DetectTwoOnes extends Module { + val io = IO(new Bundle { + val in = Input(Bool()) + val out = Output(Bool()) + }) + + val sNone :: sOne1 :: sTwo1s :: Nil = Enum(3) + val state = Reg(init = sNone) + + io.out := (state === sTwo1s) + + switch (state) { + is (sNone) { + when (io.in) { + state := sOne1 + } + } + is (sOne1) { + when (io.in) { + state := sTwo1s + } .otherwise { + state := sNone + } + } + is (sTwo1s) { + when (!io.in) { + state := sNone + } + } + } +} + +class DetectTwoOnesTester extends CookbookTester(10) { + + val dut = Module(new DetectTwoOnes) + + // Inputs and expected results + val inputs: Vec[Bool] = Vec(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) + val expected: Vec[Bool] = Vec(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) + + dut.io.in := inputs(cycle) + assert(dut.io.out === expected(cycle)) +} + +class FSMSpec extends CookbookSpec { + "DetectTwoOnes" should "work" in { + assertTesterPasses { new DetectTwoOnesTester } + } +} diff --git a/src/test/scala/cookbook/RegOfVec.scala b/src/test/scala/cookbook/RegOfVec.scala new file mode 100644 index 00000000..3e55acff --- /dev/null +++ b/src/test/scala/cookbook/RegOfVec.scala @@ -0,0 +1,33 @@ +// See LICENSE for license details. + +package cookbook + +import chisel3._ + +/* ### How do I create a Reg of type Vec? + * + * For information, please see the API documentation for Vec + * (https://chisel.eecs.berkeley.edu/api/index.html#chisel3.core.Vec) + */ +class RegOfVec extends CookbookTester(2) { + // Reg of Vec of 32-bit UInts without initialization + val regOfVec = Reg(Vec(4, UInt(32.W))) + regOfVec(0) := 123.U // a couple of assignments + regOfVec(2) := regOfVec(0) + + // Reg of Vec of 32-bit UInts initialized to zero + // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0 + // Vec(...) then constructs a Wire of these literals + // The Reg is then initialized to the value of the Wire (which gives it the same type) + val initRegOfVec = Reg(init = Vec(Seq.fill(4)(0.asUInt(32.W)))) + + // Simple test (cycle comes from superclass) + when (cycle === 2.U) { assert(regOfVec(2) === 123.U) } + for (elt <- initRegOfVec) { assert(elt === 0.U) } +} + +class RegOfVecSpec extends CookbookSpec { + "RegOfVec" should "work" in { + assertTesterPasses { new RegOfVec } + } +} |
