From 9aba55e7452981058d069b3096544d45e730dba9 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Tue, 6 Dec 2016 17:16:40 -0800 Subject: utils scaladoc examples for BitPat through CircuitMath (#398) Add examples for utils, move examples from individual apply methods to class overview scaladoc--- src/main/scala/chisel3/util/BitPat.scala | 19 ++++++++--- src/main/scala/chisel3/util/Bitwise.scala | 46 +++++++++++++++++++++++---- src/main/scala/chisel3/util/Cat.scala | 13 +++++++- src/main/scala/chisel3/util/CircuitMath.scala | 17 ++++++---- 4 files changed, 77 insertions(+), 18 deletions(-) (limited to 'src') 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 -- cgit v1.2.3 From ad53161bbb9f67e16b88ca7a508a537f88d77e05 Mon Sep 17 00:00:00 2001 From: Chick Markley Date: Wed, 7 Dec 2016 10:31:23 -0800 Subject: Support for creating chisel annotations that are consumed by firrtl (#393) * Support for creating chisel annotations that are consumed by firrtl Update annotation serialization in Driver Add DiamondAnnotation Spec that illustrates how to do simple annotations frontEnd must have dependency on firrtl Add annotation method to Module Circuit has extra optional parameter that is Seq of Annotations In Builder add annotation buffer to DynamicContext to store annotations created in modules Added explicit types on naming api methods to avoid type confusion Because some names are not available until elaboration create intermediate ChiselAnnotation that gets turned into a firrtl Annotation after elaboration In execute pass firrtl text and annotation to firrtl are now passed in through optionManager, though intermediate file .fir and .anno files are still created for inspection and/or later use * Somehow missed ChiselAnnotation * fixes for Jack's review of PR --- src/main/scala/chisel3/Driver.scala | 12 ++ src/main/scala/chisel3/package.scala | 3 + .../scala/chiselTests/AnnotatingDiamondSpec.scala | 164 +++++++++++++++++++++ src/test/scala/chiselTests/AnnotatingExample.scala | 145 ------------------ 4 files changed, 179 insertions(+), 145 deletions(-) create mode 100644 src/test/scala/chiselTests/AnnotatingDiamondSpec.scala delete mode 100644 src/test/scala/chiselTests/AnnotatingExample.scala (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index ab51ad25..646702c3 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,15 @@ 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() + + /* This passes the firrtl source and annotations directly to firrtl */ + optionsManager.firrtlOptions = optionsManager.firrtlOptions.copy( + firrtlSource = Some(firrtlString), annotations = circuit.annotations.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/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala new file mode 100644 index 00000000..3886ddd6 --- /dev/null +++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala @@ -0,0 +1,164 @@ +// 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 => + /* Do something useful with annotations here */ + 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()) -} -- cgit v1.2.3 From c5b39d05dc723daf4297c7b016de745ce4712460 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Mon, 12 Dec 2016 16:44:33 -0800 Subject: Add Cookbook examples Reg of Vec and FSM (#404) --- src/test/scala/cookbook/FSM.scala | 61 ++++++++++++++++++++++++++++++++++ src/test/scala/cookbook/RegOfVec.scala | 33 ++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/test/scala/cookbook/FSM.scala create mode 100644 src/test/scala/cookbook/RegOfVec.scala (limited to 'src') 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 } + } +} -- cgit v1.2.3 From 72e6c884b3f66a379982e5b3efc01afc563275cd Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 14 Dec 2016 12:32:04 -0800 Subject: Change noenq in ReadyValid to use an uninitialized Wire instead of zero (#364) --- src/main/scala/chisel3/util/Decoupled.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') 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. -- cgit v1.2.3 From 59a7c25d5c708305216532ec49c8120e59219f69 Mon Sep 17 00:00:00 2001 From: Chick Markley Date: Wed, 14 Dec 2016 15:31:31 -0800 Subject: Final steps for annotations getting from chisel to firrtl (#405) Pass transforms along with Annotations when calling firrtl compiler This introduces new requirement that firrtl.Transform subclasses (that are associated with an annotation) do not have parameters in their default constructor Add new test for NoDedup annotation that shows how to annotate a module instance--- src/main/scala/chisel3/Driver.scala | 10 ++- .../scala/chiselTests/AnnotatingDiamondSpec.scala | 1 - src/test/scala/chiselTests/AnnotationNoDedup.scala | 78 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/test/scala/chiselTests/AnnotationNoDedup.scala (limited to 'src') diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala index 646702c3..40c94b54 100644 --- a/src/main/scala/chisel3/Driver.scala +++ b/src/main/scala/chisel3/Driver.scala @@ -247,9 +247,17 @@ object Driver extends BackendCompilationUtilities { 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) + firrtlSource = Some(firrtlString), + annotations = circuit.annotations.toList, + customTransforms = transforms.toList) val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) { Some(firrtl.Driver.execute(optionsManager)) diff --git a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala index 3886ddd6..ff9f8e67 100644 --- a/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala +++ b/src/test/scala/chiselTests/AnnotatingDiamondSpec.scala @@ -32,7 +32,6 @@ class IdentityTransform extends Transform { getMyAnnotations(state) match { case Nil => state case myAnnotations => - /* Do something useful with annotations here */ state } } 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 _ => + } + } + } +} -- cgit v1.2.3