")
48 | ))
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage.phases
4 |
5 |
6 | import chisel3.RawModule
7 | import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation}
8 | import chisel3.stage.phases.{AddImplicitOutputFile, Elaborate}
9 |
10 | import firrtl.AnnotationSeq
11 | import firrtl.options.{Phase, StageOptions, TargetDirAnnotation}
12 | import firrtl.options.Viewer.view
13 | import org.scalatest.flatspec.AnyFlatSpec
14 | import org.scalatest.matchers.should.Matchers
15 |
16 | class AddImplicitOutputFileSpec extends AnyFlatSpec with Matchers {
17 |
18 | class Foo extends RawModule { override val desiredName = "Foo" }
19 |
20 | class Fixture { val phase: Phase = new AddImplicitOutputFile }
21 |
22 | behavior of classOf[AddImplicitOutputFile].toString
23 |
24 | it should "not override an existing ChiselOutputFileAnnotation" in new Fixture {
25 | val annotations: AnnotationSeq = Seq(
26 | ChiselGeneratorAnnotation(() => new Foo),
27 | ChiselOutputFileAnnotation("Bar") )
28 |
29 | Seq( new Elaborate, phase )
30 | .foldLeft(annotations)((a, p) => p.transform(a))
31 | .collect{ case a: ChiselOutputFileAnnotation => a.file }
32 | .toSeq should be (Seq("Bar"))
33 | }
34 |
35 | it should "generate a ChiselOutputFileAnnotation from a ChiselCircuitAnnotation" in new Fixture {
36 | val annotations: AnnotationSeq = Seq(
37 | ChiselGeneratorAnnotation(() => new Foo),
38 | TargetDirAnnotation("test_run_dir") )
39 |
40 | Seq( new Elaborate, phase )
41 | .foldLeft(annotations)((a, p) => p.transform(a))
42 | .collect{ case a: ChiselOutputFileAnnotation => a.file }
43 | .toSeq should be (Seq("Foo"))
44 | }
45 |
46 | it should "do nothing to an empty annotation sequence" in new Fixture {
47 | phase.transform(AnnotationSeq(Seq.empty)).toSeq should be (empty)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Tbl.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.testers.BasicTester
7 | import chisel3.util._
8 |
9 | class Tbl(w: Int, n: Int) extends Module {
10 | val io = IO(new Bundle {
11 | val wi = Input(UInt(log2Ceil(n).W))
12 | val ri = Input(UInt(log2Ceil(n).W))
13 | val we = Input(Bool())
14 | val d = Input(UInt(w.W))
15 | val o = Output(UInt(w.W))
16 | })
17 | val m = Mem(n, UInt(w.W))
18 | io.o := m(io.ri)
19 | when (io.we) {
20 | m(io.wi) := io.d
21 | when(io.ri === io.wi) {
22 | io.o := io.d
23 | }
24 | }
25 | }
26 |
27 | class TblTester(w: Int, n: Int, idxs: List[Int], values: List[Int]) extends BasicTester {
28 | val (cnt, wrap) = Counter(true.B, idxs.size)
29 | val dut = Module(new Tbl(w, n))
30 | val vvalues = VecInit(values.map(_.asUInt))
31 | val vidxs = VecInit(idxs.map(_.asUInt))
32 | val prev_idx = vidxs(cnt - 1.U)
33 | val prev_value = vvalues(cnt - 1.U)
34 | dut.io.wi := vidxs(cnt)
35 | dut.io.ri := prev_idx
36 | dut.io.we := true.B //TODO enSequence
37 | dut.io.d := vvalues(cnt)
38 | when (cnt > 0.U) {
39 | when (prev_idx === vidxs(cnt)) {
40 | assert(dut.io.o === vvalues(cnt))
41 | } .otherwise {
42 | assert(dut.io.o === prev_value)
43 | }
44 | }
45 | when(wrap) {
46 | stop()
47 | }
48 | }
49 |
50 | class TblSpec extends ChiselPropSpec {
51 | property("All table reads should return the previous write") {
52 | forAll(safeUIntPairN(8)) { case(w: Int, pairs: List[(Int, Int)]) =>
53 | // Provide an appropriate whenever clause.
54 | // ScalaTest will try and shrink the values on error to determine the smallest values that cause the error.
55 | whenever(w > 0 && pairs.length > 0) {
56 | val (idxs, values) = pairs.unzip
57 | assertTesterPasses{ new TblTester(w, 1 << w, idxs, values) }
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/stage/package.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3
4 |
5 | import firrtl._
6 | import firrtl.options.OptionsView
7 |
8 | import chisel3.internal.firrtl.{Circuit => ChiselCircuit}
9 |
10 | package object stage {
11 |
12 | implicit object ChiselOptionsView extends OptionsView[ChiselOptions] {
13 |
14 | def view(options: AnnotationSeq): ChiselOptions = options
15 | .collect { case a: ChiselOption => a }
16 | .foldLeft(new ChiselOptions()){ (c, x) =>
17 | x match {
18 | case _: NoRunFirrtlCompilerAnnotation.type => c.copy(runFirrtlCompiler = false)
19 | case _: PrintFullStackTraceAnnotation.type => c.copy(printFullStackTrace = true)
20 | case ChiselOutputFileAnnotation(f) => c.copy(outputFile = Some(f))
21 | case ChiselCircuitAnnotation(a) => c.copy(chiselCircuit = Some(a))
22 | }
23 | }
24 |
25 | }
26 |
27 | private[chisel3] implicit object ChiselExecutionResultView extends OptionsView[ChiselExecutionResult] {
28 |
29 | def view(options: AnnotationSeq): ChiselExecutionResult = {
30 | var chiselCircuit: Option[ChiselCircuit] = None
31 | var chirrtlCircuit: Option[String] = None
32 |
33 | options.foreach {
34 | case a@ ChiselCircuitAnnotation(b) =>
35 | chiselCircuit = Some(b)
36 | chirrtlCircuit = Some(a.getBytes.map(_.toChar).mkString)
37 | case _ =>
38 | }
39 |
40 | val fResult = firrtl.stage.phases.DriverCompatibility.firrtlResultView(options)
41 |
42 | (chiselCircuit, chirrtlCircuit) match {
43 | case (None, _) => ChiselExecutionFailure("Failed to elaborate Chisel circuit")
44 | case (Some(_), None) => ChiselExecutionFailure("Failed to convert Chisel circuit to FIRRTL")
45 | case (Some(a), Some(b)) => ChiselExecutionSuccess( Some(a), b, Some(fResult))
46 | }
47 |
48 | }
49 |
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/ComplexAssign.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.testers.BasicTester
7 | import chisel3.util._
8 | import org.scalacheck.Shrink
9 |
10 | class Complex[T <: Data](val re: T, val im: T) extends Bundle {
11 | override def cloneType: this.type =
12 | new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type]
13 | }
14 |
15 | class ComplexAssign(w: Int) extends Module {
16 | val io = IO(new Bundle {
17 | val e = Input(Bool())
18 | val in = Input(new Complex(UInt(w.W), UInt(w.W)))
19 | val out = Output(new Complex(UInt(w.W), UInt(w.W)))
20 | })
21 | when (io.e) {
22 | val tmp = Wire(new Complex(UInt(w.W), UInt(w.W)))
23 | tmp := io.in
24 | io.out.re := tmp.re
25 | io.out.im := tmp.im
26 | } .otherwise {
27 | io.out.re := 0.U
28 | io.out.im := 0.U
29 | }
30 | }
31 |
32 | class ComplexAssignTester(enList: List[Boolean], re: Int, im: Int) extends BasicTester {
33 | val (cnt, wrap) = Counter(true.B, enList.size)
34 | val dut = Module(new ComplexAssign(32))
35 | dut.io.in.re := re.asUInt
36 | dut.io.in.im := im.asUInt
37 | dut.io.e := VecInit(enList.map(_.asBool))(cnt)
38 | val re_correct = dut.io.out.re === Mux(dut.io.e, dut.io.in.re, 0.U)
39 | val im_correct = dut.io.out.im === Mux(dut.io.e, dut.io.in.im, 0.U)
40 | assert(re_correct && im_correct)
41 | when(wrap) {
42 | stop()
43 | }
44 | }
45 |
46 | class ComplexAssignSpec extends ChiselPropSpec {
47 | property("All complex assignments should return the correct result") {
48 | // Disable shrinking on error.
49 | implicit val noShrinkListVal = Shrink[List[Boolean]](_ => Stream.empty)
50 | implicit val noShrinkInt = Shrink[Int](_ => Stream.empty)
51 | forAll(enSequence(2), safeUInts, safeUInts) { (en: List[Boolean], re: Int, im: Int) =>
52 | assertTesterPasses{ new ComplexAssignTester(en, re, im) }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/TransitNameSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 | package chiselTests
3 |
4 |
5 | import chisel3._
6 | import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
7 | import chisel3.util.TransitName
8 |
9 | import firrtl.FirrtlExecutionSuccess
10 | import org.scalatest.flatspec.AnyFlatSpec
11 | import org.scalatest.matchers.should.Matchers
12 |
13 | class TransitNameSpec extends AnyFlatSpec with Matchers {
14 |
15 | class MyModule extends RawModule {
16 | val io = IO(new Bundle{})
17 | override val desiredName: String = "MyModule"
18 | }
19 |
20 | /** A top-level module that instantiates three copies of MyModule */
21 | class Top extends RawModule {
22 |
23 | /* Assign the IO of a new MyModule instance to value "foo". The instance will be named "MyModule". */
24 | val foo = Module(new MyModule).io
25 |
26 | /* Assign the IO of a new MyModule instance to value "bar". The instance will be named "bar". */
27 | val bar = {
28 | val x = Module(new MyModule)
29 | TransitName(x.io, x) // TransitName returns the first argument
30 | }
31 |
32 | /* Assign the IO of a new MyModule instance to value "baz". The instance will be named "baz_generated". */
33 | val baz = {
34 | val x = Module(new MyModule)
35 | TransitName.withSuffix("_generated")(x.io, x) // TransitName returns the first argument
36 | }
37 |
38 | }
39 |
40 | it should "transit a name" in {
41 |
42 | val firrtl = (new ChiselStage)
43 | .emitFirrtl(new Top, Array("--target-dir", "test_run_dir/TransitNameSpec"))
44 |
45 | info("""output FIRRTL includes "inst MyModule"""")
46 | firrtl should include ("inst MyModule of MyModule")
47 |
48 | info("""output FIRRTL includes "inst bar"""")
49 | firrtl should include ("inst bar of MyModule")
50 |
51 | info("""output FIRRTL includes "inst baz_generated"""")
52 | firrtl should include ("inst baz_generated of MyModule")
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/macros/src/main/scala/chisel3/SourceInfoDoc.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3
4 |
5 | /** Provides ScalaDoc information for "hidden" `do_*` methods
6 | *
7 | * Mix this into classes/objects that have `do_*` methods to get access to the shared `SourceInfoTransformMacro`
8 | * ScalaDoc group and the lengthy `groupdesc` below.
9 | *
10 | * @groupdesc SourceInfoTransformMacro
11 | *
12 | *
13 | * '''These internal methods are not part of the public-facing API!'''
14 | *
15 | *
16 | *
17 | * The equivalent public-facing methods do not have the `do_` prefix or have the same name. Use and look at the
18 | * documentation for those. If you want left shift, use `<<`, not `do_<<`. If you want conversion to a
19 | * [[scala.collection.Seq Seq]] of [[Bool]]s look at the `asBools` above, not the one below. Users can safely ignore
20 | * every method in this group!
21 | *
22 | * 🐉🐉🐉 '''Here be dragons...''' 🐉🐉🐉
23 | *
24 | *
25 | *
26 | * These `do_X` methods are used to enable both implicit passing of SourceInfo and [[chisel3.CompileOptions]]
27 | * while also supporting chained apply methods. In effect all "normal" methods that you, as a user, will use in your
28 | * designs, are converted to their "hidden", `do_*`, via macro transformations. Without using macros here, only one
29 | * of the above wanted behaviors is allowed (implicit passing and chained applies)---the compiler interprets a
30 | * chained apply as an explicit 'implicit' argument and will throw type errors.
31 | *
32 | * The "normal", public-facing methods then take no SourceInfo. However, a macro transforms this public-facing method
33 | * into a call to an internal, hidden `do_*` that takes an explicit SourceInfo by inserting an
34 | * `implicitly[SourceInfo]` as the explicit argument.
35 | *
36 | * @groupprio SourceInfoTransformMacro 1001
37 | */
38 | trait SourceInfoDoc
39 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/ChiselExecutionOptions.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3
4 |
5 | import chisel3.stage.{NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation}
6 |
7 | import firrtl.{AnnotationSeq, ExecutionOptionsManager, ComposableOptions}
8 |
9 | //TODO: provide support for running firrtl as separate process, could alternatively be controlled by external driver
10 | //TODO: provide option for not saving chirrtl file, instead calling firrtl with in memory chirrtl
11 | /**
12 | * Options that are specific to chisel.
13 | *
14 | * @param runFirrtlCompiler when true just run chisel, when false run chisel then compile its output with firrtl
15 | * @note this extends FirrtlExecutionOptions which extends CommonOptions providing easy access to down chain options
16 | */
17 | case class ChiselExecutionOptions(
18 | runFirrtlCompiler: Boolean = true,
19 | printFullStackTrace: Boolean = false
20 | // var runFirrtlAsProcess: Boolean = false
21 | ) extends ComposableOptions {
22 |
23 | def toAnnotations: AnnotationSeq =
24 | (if (!runFirrtlCompiler) { Seq(NoRunFirrtlCompilerAnnotation) } else { Seq() }) ++
25 | (if (printFullStackTrace) { Some(PrintFullStackTraceAnnotation) } else { None })
26 |
27 | }
28 |
29 | trait HasChiselExecutionOptions {
30 | self: ExecutionOptionsManager =>
31 |
32 | var chiselOptions = ChiselExecutionOptions()
33 |
34 | parser.note("chisel3 options")
35 |
36 | parser.opt[Unit]("no-run-firrtl")
37 | .abbr("chnrf")
38 | .foreach { _ =>
39 | chiselOptions = chiselOptions.copy(runFirrtlCompiler = false)
40 | }
41 | .text("Stop after chisel emits chirrtl file")
42 |
43 | parser.opt[Unit]("full-stacktrace")
44 | .foreach { _ =>
45 | chiselOptions = chiselOptions.copy(printFullStackTrace = true)
46 | }
47 | .text("Do not trim stack trace")
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/aop/injecting/InjectingTransform.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.aop.injecting
4 |
5 | import firrtl.{ChirrtlForm, CircuitForm, CircuitState, Transform, ir}
6 |
7 | import scala.collection.mutable
8 |
9 | /** Appends statements contained in [[InjectStatement]] annotations to the end of their corresponding modules
10 | *
11 | * Implemented with Chisel Aspects and the [[chisel3.aop.injecting]] library
12 | */
13 | class InjectingTransform extends Transform {
14 | override def inputForm: CircuitForm = ChirrtlForm
15 | override def outputForm: CircuitForm = ChirrtlForm
16 |
17 | override def execute(state: CircuitState): CircuitState = {
18 |
19 | val addStmtMap = mutable.HashMap[String, Seq[ir.Statement]]()
20 | val addModules = mutable.ArrayBuffer[ir.DefModule]()
21 |
22 | // Populate addStmtMap and addModules, return annotations in InjectStatements, and omit InjectStatement annotation
23 | val newAnnotations = state.annotations.flatMap {
24 | case InjectStatement(mt, s, addedModules, annotations) =>
25 | addModules ++= addedModules
26 | addStmtMap(mt.module) = s +: addStmtMap.getOrElse(mt.module, Nil)
27 | annotations
28 | case other => Seq(other)
29 | }
30 |
31 | // Append all statements to end of corresponding modules
32 | val newModules = state.circuit.modules.map { m: ir.DefModule =>
33 | m match {
34 | case m: ir.Module if addStmtMap.contains(m.name) =>
35 | m.copy(body = ir.Block(m.body +: addStmtMap(m.name)))
36 | case m: _root_.firrtl.ir.ExtModule if addStmtMap.contains(m.name) =>
37 | ir.Module(m.info, m.name, m.ports, ir.Block(addStmtMap(m.name)))
38 | case other: ir.DefModule => other
39 | }
40 | }
41 |
42 | // Return updated circuit and annotations
43 | val newCircuit = state.circuit.copy(modules = newModules ++ addModules)
44 | state.copy(annotations = newAnnotations, circuit = newCircuit)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/twine/IOInterface.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.twine.util
4 |
5 | import chisel3._
6 | import chisel3.util._
7 | import chisel3.twine._
8 | import chisel3.experimental._
9 | import chisel3.internal._
10 | import chisel3.internal.firrtl._
11 | import chisel3.internal.sourceinfo._
12 |
13 | abstract class TwineIOCtrl extends Bundle{
14 |
15 | }
16 |
17 | class ValidInterface extends Bundle with ValidInterfaceInternal{
18 | val valid = Input(Bool())
19 | }
20 |
21 | class DecoupledInterface extends Bundle with DecoupledInterfaceInternal{
22 | val valid = Input(Bool())
23 | val ready = Output(Bool())
24 | }
25 |
26 | class OutOfOrderInterface(val size_of_reorder_buffer: Int) extends Bundle with OutOfOrderInterfaceInternal{
27 | val valid = Input(Bool())
28 | val ready = Output(Bool())
29 | val ticket_num = Input(UInt(log2Ceil(size_of_reorder_buffer).W))
30 | }
31 |
32 |
33 | class NoIOCtrl extends TwineIOCtrl with NoIOCtrlInternal{
34 |
35 | }
36 |
37 | class TightlyCoupledIOCtrl(val delay: Int) extends TwineIOCtrl with TightlyCoupledIOCtrlInternal{
38 | val stall = Input(Bool())
39 | val stuck = Output(Bool())
40 | val in = new ValidInterface
41 | val out = Flipped(new ValidInterface)
42 | }
43 |
44 | class ValidIOCtrl extends TwineIOCtrl with ValidIOCtrlInternal{
45 | val in = new ValidInterface
46 | val out = Flipped(new ValidInterface)
47 | val stall = Input(Bool())
48 | val stuck = Output(Bool())
49 | }
50 |
51 | class DecoupledIOCtrl(val size_of_receiving_buffer: Int, val size_of_sending_buffer: Int) extends TwineIOCtrl with DecoupledIOCtrlInternal {
52 | val in = new DecoupledInterface
53 | val out = Flipped(new DecoupledInterface)
54 | }
55 |
56 | class OutOfOrderIOCtrl(val size_of_reorder_buffer: Int) extends TwineIOCtrl with OutOfOrderIOCtrlInternal{
57 | val in = new OutOfOrderInterface(size_of_reorder_buffer)
58 | val out = Flipped(new OutOfOrderInterface(size_of_reorder_buffer))
59 | }
60 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage.phases
4 |
5 |
6 | import chisel3.stage.{ChiselOutputFileAnnotation, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation}
7 | import chisel3.stage.phases.Checks
8 |
9 | import firrtl.AnnotationSeq
10 | import firrtl.annotations.NoTargetAnnotation
11 | import firrtl.options.{OptionsException, Phase}
12 | import org.scalatest.flatspec.AnyFlatSpec
13 | import org.scalatest.matchers.should.Matchers
14 |
15 | class ChecksSpec extends AnyFlatSpec with Matchers {
16 |
17 | def checkExceptionMessage(phase: Phase, annotations: AnnotationSeq, messageStart: String): Unit =
18 | intercept[OptionsException]{ phase.transform(annotations) }.getMessage should startWith(messageStart)
19 |
20 | class Fixture { val phase: Phase = new Checks }
21 |
22 | behavior of classOf[Checks].toString
23 |
24 | it should "do nothing on sane annotation sequences" in new Fixture {
25 | val a = Seq(NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation)
26 | phase.transform(a).toSeq should be (a)
27 | }
28 |
29 | it should "throw an OptionsException if more than one NoRunFirrtlCompilerAnnotation is specified" in new Fixture {
30 | val a = Seq(NoRunFirrtlCompilerAnnotation, NoRunFirrtlCompilerAnnotation)
31 | checkExceptionMessage(phase, a, "At most one NoRunFirrtlCompilerAnnotation")
32 | }
33 |
34 | it should "throw an OptionsException if more than one PrintFullStackTraceAnnotation is specified" in new Fixture {
35 | val a = Seq(PrintFullStackTraceAnnotation, PrintFullStackTraceAnnotation)
36 | checkExceptionMessage(phase, a, "At most one PrintFullStackTraceAnnotation")
37 | }
38 |
39 | it should "throw an OptionsException if more than one ChiselOutputFileAnnotation is specified" in new Fixture {
40 | val a = Seq(ChiselOutputFileAnnotation("foo"), ChiselOutputFileAnnotation("bar"))
41 | checkExceptionMessage(phase, a, "At most one Chisel output file")
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/macros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.internal
4 |
5 | import scala.reflect.macros.whitebox.Context
6 | import scala.annotation.{StaticAnnotation, compileTimeOnly}
7 | import scala.language.experimental.macros
8 |
9 | // Workaround for https://github.com/sbt/sbt/issues/3966
10 | object RuntimeDeprecatedTransform
11 | class RuntimeDeprecatedTransform(val c: Context) {
12 | import c.universe._
13 |
14 | /** Adds a Builder.deprecated(...) call based on the contents of a plain @deprecated annotation.
15 | */
16 | def runtimeDeprecated(annottees: c.Tree*): c.Tree = {
17 | val transformed = annottees.map(annottee => annottee match {
18 | case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => {
19 | val Modifiers(_, _, annotations) = mods
20 | val annotationMessage = annotations.collect { // get all messages from deprecated annotations
21 | case q"new deprecated($desc, $since)" => desc
22 | } match { // ensure there's only one and return it
23 | case msg :: Nil => msg
24 | case _ => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion must be used with exactly one @deprecated annotation, got annotations $annotations")
25 | }
26 | val message = s"$tname is deprecated: $annotationMessage"
27 | val transformedExpr = q""" {
28 | _root_.chisel3.internal.Builder.deprecated($message)
29 | $expr
30 | } """
31 | q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr"
32 | }
33 | case other => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion may only be used on defs, got ${showCode(other)}")
34 | })
35 | q"..$transformed"
36 | }
37 | }
38 |
39 | @compileTimeOnly("enable macro paradise to expand macro annotations")
40 | class chiselRuntimeDeprecated extends StaticAnnotation {
41 | def macroTransform(annottees: Any*): Any = macro chisel3.internal.RuntimeDeprecatedTransform.runtimeDeprecated
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Stack.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 | import chisel3.util._
8 |
9 | class ChiselStack(val depth: Int) extends Module {
10 | val io = IO(new Bundle {
11 | val push = Input(Bool())
12 | val pop = Input(Bool())
13 | val en = Input(Bool())
14 | val dataIn = Input(UInt(32.W))
15 | val dataOut = Output(UInt(32.W))
16 | })
17 |
18 | val stack_mem = Mem(depth, UInt(32.W))
19 | val sp = RegInit(0.U(log2Ceil(depth + 1).W))
20 | val out = RegInit(0.U(32.W))
21 |
22 | when (io.en) {
23 | when(io.push && (sp < depth.asUInt)) {
24 | stack_mem(sp) := io.dataIn
25 | sp := sp +% 1.U
26 | } .elsewhen(io.pop && (sp > 0.U)) {
27 | sp := sp -% 1.U
28 | }
29 | when (sp > 0.U) {
30 | out := stack_mem(sp -% 1.U)
31 | }
32 | }
33 | io.dataOut := out
34 | }
35 |
36 | /*
37 | class StackTester(c: Stack) extends Tester(c) {
38 | var nxtDataOut = 0
39 | var dataOut = 0
40 | val stack = new ScalaStack[Int]()
41 |
42 | for (t <- 0 until 16) {
43 | val enable = rnd.nextInt(2)
44 | val push = rnd.nextInt(2)
45 | val pop = rnd.nextInt(2)
46 | val dataIn = rnd.nextInt(256)
47 |
48 | if (enable == 1) {
49 | dataOut = nxtDataOut
50 | if (push == 1 && stack.length < c.depth) {
51 | stack.push(dataIn)
52 | } else if (pop == 1 && stack.length > 0) {
53 | stack.pop()
54 | }
55 | if (stack.length > 0) {
56 | nxtDataOut = stack.top
57 | }
58 | }
59 |
60 | poke(c.io.pop, pop)
61 | poke(c.io.push, push)
62 | poke(c.io.en, enable)
63 | poke(c.io.dataIn, dataIn)
64 | step(1)
65 | expect(c.io.dataOut, dataOut)
66 | }
67 | }
68 | */
69 |
70 | class StackSpec extends ChiselPropSpec {
71 |
72 | property("Stack should elaborate") {
73 | ChiselStage.elaborate { new ChiselStack(2) }
74 | }
75 |
76 | ignore("StackTester should return the correct result") { }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/stage/phases/Checks.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.stage.phases
4 |
5 | import chisel3.stage.{ChiselOutputFileAnnotation, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation}
6 |
7 | import firrtl.AnnotationSeq
8 | import firrtl.annotations.Annotation
9 | import firrtl.options.{Dependency, OptionsException, Phase, PreservesAll}
10 |
11 | /** Sanity checks an [[firrtl.AnnotationSeq]] before running the main [[firrtl.options.Phase]]s of
12 | * [[chisel3.stage.ChiselStage]].
13 | */
14 | class Checks extends Phase with PreservesAll[Phase] {
15 |
16 | override val dependents = Seq(Dependency[Elaborate])
17 |
18 | def transform(annotations: AnnotationSeq): AnnotationSeq = {
19 | val noF, st, outF = collection.mutable.ListBuffer[Annotation]()
20 | annotations.foreach {
21 | case a: NoRunFirrtlCompilerAnnotation.type => a +=: noF
22 | case a: PrintFullStackTraceAnnotation.type => a +=: st
23 | case a: ChiselOutputFileAnnotation => a +=: outF
24 | case _ =>
25 | }
26 |
27 | if (noF.size > 1) {
28 | throw new OptionsException(
29 | s"""|At most one NoRunFirrtlCompilerAnnotation can be specified, but found '${noF.size}'. Did you duplicate:
30 | | - option or annotation: -chnrf, --no-run-firrtl, NoRunFirrtlCompilerAnnotation
31 | |""".stripMargin)
32 | }
33 |
34 | if (st.size > 1) {
35 | throw new OptionsException(
36 | s"""|At most one PrintFullStackTraceAnnotation can be specified, but found '${noF.size}'. Did you duplicate:
37 | | - option or annotation: --full-stacktrace, PrintFullStackTraceAnnotation
38 | |""".stripMargin)
39 | }
40 |
41 | if (outF.size > 1) {
42 | throw new OptionsException(
43 | s"""|At most one Chisel output file can be specified but found '${outF.size}'. Did you duplicate:
44 | | - option or annotation: --chisel-output-file, ChiselOutputFileAnnotation
45 | |""".stripMargin)
46 | }
47 |
48 | annotations
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/MultiClock.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3
4 |
5 | import chisel3.internal._
6 |
7 | import scala.language.experimental.macros
8 |
9 | object withClockAndReset {
10 | /** Creates a new Clock and Reset scope
11 | *
12 | * @param clock the new implicit Clock
13 | * @param reset the new implicit Reset
14 | * @param block the block of code to run with new implicit Clock and Reset
15 | * @return the result of the block
16 | */
17 | def apply[T](clock: Clock, reset: Reset)(block: => T): T = {
18 | // Save parentScope
19 | val parentClock = Builder.currentClock
20 | val parentReset = Builder.currentReset
21 |
22 | Builder.currentClock = Some(clock)
23 | Builder.currentReset = Some(reset)
24 |
25 | val res = block // execute block
26 |
27 | // Return to old scope
28 | Builder.currentClock = parentClock
29 | Builder.currentReset = parentReset
30 | res
31 | }
32 | }
33 |
34 | object withClock {
35 | /** Creates a new Clock scope
36 | *
37 | * @param clock the new implicit Clock
38 | * @param block the block of code to run with new implicit Clock
39 | * @return the result of the block
40 | */
41 | def apply[T](clock: Clock)(block: => T): T = {
42 | // Save parentScope
43 | val parentClock = Builder.currentClock
44 | Builder.currentClock = Some(clock)
45 | val res = block // execute block
46 | // Return to old scope
47 | Builder.currentClock = parentClock
48 | res
49 | }
50 | }
51 |
52 | object withReset {
53 | /** Creates a new Reset scope
54 | *
55 | * @param reset the new implicit Reset
56 | * @param block the block of code to run with new implicit Reset
57 | * @return the result of the block
58 | */
59 | def apply[T](reset: Reset)(block: => T): T = {
60 | // Save parentScope
61 | val parentReset = Builder.currentReset
62 | Builder.currentReset = Some(reset)
63 | val res = block // execute block
64 | // Return to old scope
65 | Builder.currentReset = parentReset
66 | res
67 | }
68 |
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/IllegalRefSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 |
8 | object IllegalRefSpec {
9 | class IllegalRefInner extends RawModule {
10 | val io = IO(new Bundle {
11 | val i = Input(Bool())
12 | val o = Output(Bool())
13 | })
14 | val x = io.i & io.i
15 | io.o := io.i
16 | }
17 |
18 | class IllegalRefOuter(useConnect: Boolean) extends RawModule {
19 | val io = IO(new Bundle {
20 | val a = Input(Bool())
21 | val b = Input(Bool())
22 | val out = Output(Bool())
23 | })
24 |
25 | val inst = Module(new IllegalRefInner)
26 | io.out := inst.io.o
27 | inst.io.i := io.a
28 | val x = WireInit(io.b)
29 | if (useConnect) {
30 | val z = WireInit(inst.x) // oops
31 | } else {
32 | val z = inst.x & inst.x // oops
33 | }
34 | }
35 |
36 | class CrossWhenConnect(useConnect: Boolean) extends RawModule {
37 | val io = IO(new Bundle {
38 | val i = Input(Bool())
39 | val o = Output(Bool())
40 | })
41 | private var tmp: Option[Bool] = None
42 | when (io.i) {
43 | val x = io.i & io.i
44 | tmp = Some(x)
45 | }
46 | if (useConnect) {
47 | io.o := tmp.get
48 | } else {
49 | val z = tmp.get & tmp.get
50 | io.o := io.i
51 | }
52 | }
53 | }
54 |
55 | class IllegalRefSpec extends ChiselFlatSpec with Utils {
56 | import IllegalRefSpec._
57 |
58 | val variants = Map("a connect" -> true, "an op" -> false)
59 |
60 | variants.foreach {
61 | case (k, v) =>
62 | s"Illegal cross-module references in ${k}" should "fail" in {
63 | a [ChiselException] should be thrownBy extractCause[ChiselException] {
64 | ChiselStage.elaborate { new IllegalRefOuter(v) }
65 | }
66 | }
67 |
68 | s"Using a signal that has escaped its enclosing when scope in ${k}" should "fail" in {
69 | a [ChiselException] should be thrownBy extractCause[ChiselException] {
70 | ChiselStage.elaborate { new CrossWhenConnect(v) }
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/ChiselStageSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 |
8 | import org.scalatest.flatspec.AnyFlatSpec
9 | import org.scalatest.matchers.should.Matchers
10 |
11 | import firrtl.options.Dependency
12 |
13 | object ChiselStageSpec {
14 |
15 | class Foo extends MultiIOModule {
16 | val addr = IO(Input(UInt(4.W)))
17 | val out = IO(Output(Bool()))
18 | val bar = SyncReadMem(8, Bool())
19 | out := bar(addr)
20 | }
21 |
22 | }
23 |
24 | class ChiselStageSpec extends AnyFlatSpec with Matchers {
25 |
26 | import ChiselStageSpec._
27 |
28 | private trait ChiselStageFixture {
29 | val stage = new ChiselStage
30 | }
31 |
32 | behavior of "ChiselStage.emitChirrtl"
33 |
34 | it should "return a CHIRRTL string" in new ChiselStageFixture {
35 | stage.emitChirrtl(new Foo) should include ("infer mport")
36 | }
37 |
38 | behavior of "ChiselStage.emitFirrtl"
39 |
40 | it should "return a High FIRRTL string" in new ChiselStageFixture {
41 | stage.emitFirrtl(new Foo) should include ("mem bar")
42 | }
43 |
44 | behavior of "ChiselStage.emitVerilog"
45 |
46 | it should "return a Verilog string" in new ChiselStageFixture {
47 | stage.emitVerilog(new Foo) should include ("endmodule")
48 | }
49 |
50 | behavior of "ChiselStage$.elaborate"
51 |
52 | it should "generate a Chisel circuit from a Chisel module" in {
53 | ChiselStage.elaborate(new Foo)
54 | }
55 |
56 | behavior of "ChiselStage$.convert"
57 |
58 | it should "generate a CHIRRTL circuit from a Chisel module" in {
59 | ChiselStage.convert(new Foo)
60 | }
61 |
62 | behavior of "ChiselStage phase ordering"
63 |
64 | it should "only run elaboration once" in new ChiselStageFixture {
65 | info("Phase order is:\n" + stage.phaseManager.prettyPrint(" "))
66 |
67 | val order = stage.phaseManager.flattenedTransformOrder.map(Dependency.fromTransform)
68 |
69 | info("Elaborate only runs once")
70 | exactly (1, order) should be (Dependency[chisel3.stage.phases.Elaborate])
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/util/Reg.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.util
4 |
5 | import chisel3._
6 |
7 | object RegEnable {
8 | /** Returns a register with the specified next, update enable gate, and no reset initialization.
9 | *
10 | * @example {{{
11 | * val regWithEnable = RegEnable(nextVal, ena)
12 | * }}}
13 | */
14 | def apply[T <: Data](next: T, enable: Bool): T = {
15 | val r = Reg(chiselTypeOf(next))
16 | when (enable) { r := next }
17 | r
18 | }
19 |
20 | /** Returns a register with the specified next, update enable gate, and reset initialization.
21 | *
22 | * @example {{{
23 | * val regWithEnableAndReset = RegEnable(nextVal, 0.U, ena)
24 | * }}}
25 | */
26 | def apply[T <: Data](next: T, init: T, enable: Bool): T = {
27 | val r = RegInit(init)
28 | when (enable) { r := next }
29 | r
30 | }
31 | }
32 |
33 | object ShiftRegister
34 | {
35 | /** Returns the n-cycle delayed version of the input signal.
36 | *
37 | * @param in input to delay
38 | * @param n number of cycles to delay
39 | * @param en enable the shift
40 | *
41 | * @example {{{
42 | * val regDelayTwo = ShiftRegister(nextVal, 2, ena)
43 | * }}}
44 | */
45 | def apply[T <: Data](in: T, n: Int, en: Bool = true.B): T = {
46 | // The order of tests reflects the expected use cases.
47 | if (n != 0) {
48 | RegEnable(apply(in, n-1, en), en)
49 | } else {
50 | in
51 | }
52 | }
53 |
54 | /** Returns the n-cycle delayed version of the input signal with reset initialization.
55 | *
56 | * @param in input to delay
57 | * @param n number of cycles to delay
58 | * @param resetData reset value for each register in the shift
59 | * @param en enable the shift
60 | *
61 | * @example {{{
62 | * val regDelayTwoReset = ShiftRegister(nextVal, 2, 0.U, ena)
63 | * }}}
64 | */
65 | def apply[T <: Data](in: T, n: Int, resetData: T, en: Bool): T = {
66 | // The order of tests reflects the expected use cases.
67 | if (n != 0) {
68 | RegEnable(apply(in, n-1, resetData, en), resetData, en)
69 | } else {
70 | in
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/VectorPacketIO.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.testers.BasicTester
7 | import chisel3.util._
8 |
9 | /**
10 | * This test used to fail when assignment statements were
11 | * contained in DeqIO and EnqIO constructors.
12 | * The symptom is creation of a firrtl file
13 | * with missing declarations, the problem is exposed by
14 | * the creation of the val outs in VectorPacketIO
15 | *
16 | * NOTE: The problem does not exist now because the initialization
17 | * code has been removed from DeqIO and EnqIO
18 | *
19 | * IMPORTANT: The canonical way to initialize a decoupled inteface is still being debated.
20 | */
21 | class Packet extends Bundle {
22 | val header = UInt(1.W)
23 | }
24 |
25 | /**
26 | * The problem occurs with just the ins or the outs
27 | * lines also.
28 | * The problem does not occur if the Vec is taken out
29 | */
30 | class VectorPacketIO(val n: Int) extends Bundle {
31 | val ins = Vec(n, chisel3.util.DeqIO(new Packet()))
32 | val outs = Vec(n, chisel3.util.EnqIO(new Packet()))
33 | }
34 |
35 | /**
36 | * a module uses the vector based IO bundle
37 | * the value of n does not affect the error
38 | */
39 | class BrokenVectorPacketModule extends Module {
40 | val n = 4
41 | val io = IO(new VectorPacketIO(n))
42 |
43 | // Avoid a "Reference io is not fully initialized" error from firrtl.
44 | for (i <- 0 until n) {
45 | io.outs(i) <> io.ins(i)
46 | }
47 |
48 | /* the following method of initializing the circuit may change in the future */
49 | io.ins.foreach(_.nodeq())
50 | io.outs.foreach(_.noenq())
51 | }
52 |
53 | class VectorPacketIOUnitTester extends BasicTester {
54 | val dut = Module(new BrokenVectorPacketModule)
55 | dut.io <> DontCare
56 |
57 | // This counter just makes the test end quicker
58 | val c = Counter(1)
59 | when(c.inc()) {
60 | stop()
61 | }
62 | }
63 |
64 | class VectorPacketIOUnitTesterSpec extends ChiselFlatSpec {
65 | "a circuit using an io containing a vector of EnqIO wrapped packets" should
66 | "compile and run" in {
67 | assertTesterPasses {
68 | new VectorPacketIOUnitTester
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/util/BlackBoxUtils.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.util
4 |
5 | import chisel3._
6 | import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform}
7 | import firrtl.transforms.{BlackBoxPathAnno, BlackBoxResourceAnno, BlackBoxInlineAnno, BlackBoxSourceHelper}
8 |
9 | trait HasBlackBoxResource extends BlackBox {
10 | self: BlackBox =>
11 |
12 | @deprecated("Use addResource instead", "3.2")
13 | def setResource(blackBoxResource: String): Unit = addResource(blackBoxResource)
14 |
15 | /** Copies a resource file to the target directory
16 | *
17 | * Resource files are located in project_root/src/main/resources/.
18 | * Example of adding the resource file project_root/src/main/resources/blackbox.v:
19 | * {{{
20 | * addResource("/blackbox.v")
21 | * }}}
22 | */
23 | def addResource(blackBoxResource: String): Unit = {
24 | val anno = new ChiselAnnotation with RunFirrtlTransform {
25 | def toFirrtl = BlackBoxResourceAnno(self.toNamed, blackBoxResource)
26 | def transformClass = classOf[BlackBoxSourceHelper]
27 | }
28 | chisel3.experimental.annotate(anno)
29 | }
30 | }
31 |
32 | trait HasBlackBoxInline extends BlackBox {
33 | self: BlackBox =>
34 |
35 | def setInline(blackBoxName: String, blackBoxInline: String): Unit = {
36 | val anno = new ChiselAnnotation with RunFirrtlTransform {
37 | def toFirrtl = BlackBoxInlineAnno(self.toNamed, blackBoxName, blackBoxInline)
38 | def transformClass = classOf[BlackBoxSourceHelper]
39 | }
40 | chisel3.experimental.annotate(anno)
41 | }
42 | }
43 |
44 | trait HasBlackBoxPath extends BlackBox {
45 | self: BlackBox =>
46 |
47 | /** Copies a file to the target directory
48 | *
49 | * This works with absolute and relative paths. Relative paths are relative
50 | * to the current working directory, which is generally not the same as the
51 | * target directory.
52 | */
53 | def addPath(blackBoxPath: String): Unit = {
54 | val anno = new ChiselAnnotation with RunFirrtlTransform {
55 | def toFirrtl = BlackBoxPathAnno(self.toNamed, blackBoxPath)
56 | def transformClass = classOf[BlackBoxSourceHelper]
57 | }
58 | chisel3.experimental.annotate(anno)
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/MultiAssign.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.testers.BasicTester
7 | import chisel3.stage.ChiselStage
8 | import chisel3.util._
9 |
10 | class LastAssignTester() extends BasicTester {
11 | val countOnClockCycles = true.B
12 | val (cnt, wrap) = Counter(countOnClockCycles,2)
13 |
14 | val test = Wire(UInt(4.W))
15 | assert(test === 7.U) // allow read references before assign references
16 |
17 | test := 13.U
18 | assert(test === 7.U) // output value should be position-independent
19 |
20 | test := 7.U
21 | assert(test === 7.U) // this obviously should work
22 |
23 | when(cnt === 1.U) {
24 | stop()
25 | }
26 | }
27 |
28 | class MultiAssignSpec extends ChiselFlatSpec {
29 | "The last assignment" should "be used when multiple assignments happen" in {
30 | assertTesterPasses{ new LastAssignTester }
31 | }
32 | }
33 |
34 | class IllegalAssignSpec extends ChiselFlatSpec with Utils {
35 | "Reassignments to literals" should "be disallowed" in {
36 | intercept[chisel3.internal.ChiselException] {
37 | extractCause[ChiselException] {
38 | ChiselStage.elaborate{
39 | new BasicTester {
40 | 15.U := 7.U
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
47 | "Reassignments to ops" should "be disallowed" in {
48 | intercept[chisel3.internal.ChiselException] {
49 | extractCause[ChiselException] {
50 | ChiselStage.elaborate{
51 | new BasicTester {
52 | (15.U + 1.U) := 7.U
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
59 | "Reassignments to bit slices" should "be disallowed" in {
60 | intercept[chisel3.internal.ChiselException] {
61 | extractCause[ChiselException] {
62 | ChiselStage.elaborate{
63 | new BasicTester {
64 | (15.U)(1, 0) := 7.U
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
71 | "Bulk-connecting two read-only nodes" should "be disallowed" in {
72 | intercept[chisel3.internal.ChiselException] {
73 | extractCause[ChiselException] {
74 | ChiselStage.elaborate{
75 | new BasicTester {
76 | (15.U + 1.U) <> 7.U
77 | }
78 | }
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Reg.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.util._
7 | import chisel3.experimental.DataMirror
8 | import chisel3.stage.ChiselStage
9 | import chisel3.testers.BasicTester
10 |
11 | class RegSpec extends ChiselFlatSpec {
12 | "Reg" should "be of the same type and width as t" in {
13 | class RegOutTypeWidthTester extends BasicTester {
14 | val reg = Reg(UInt(2.W))
15 | DataMirror.widthOf(reg) should be (2.W)
16 | }
17 | ChiselStage.elaborate{ new RegOutTypeWidthTester }
18 | }
19 |
20 | "RegNext" should "be of unknown width" in {
21 | class RegUnknownWidthTester extends BasicTester {
22 | val reg1 = RegNext(2.U(3.W))
23 | DataMirror.widthOf(reg1).known should be (false)
24 | val reg2 = RegNext(2.U(3.W), 4.U)
25 | DataMirror.widthOf(reg2).known should be (false)
26 | val reg3 = RegNext(2.U(3.W), 4.U(5.W))
27 | DataMirror.widthOf(reg3).known should be (false)
28 | }
29 | ChiselStage.elaborate { new RegUnknownWidthTester }
30 | }
31 |
32 | "RegInit" should "have width only if specified in the literal" in {
33 | class RegForcedWidthTester extends BasicTester {
34 | val reg1 = RegInit(20.U)
35 | DataMirror.widthOf(reg1).known should be (false)
36 | val reg2 = RegInit(20.U(7.W))
37 | DataMirror.widthOf(reg2) should be (7.W)
38 | }
39 | ChiselStage.elaborate{ new RegForcedWidthTester }
40 | }
41 | }
42 |
43 | class ShiftTester(n: Int) extends BasicTester {
44 | val (cntVal, done) = Counter(true.B, n)
45 | val start = 23.U
46 | val sr = ShiftRegister(cntVal + start, n)
47 | when(done) {
48 | assert(sr === start)
49 | stop()
50 | }
51 | }
52 |
53 | class ShiftResetTester(n: Int) extends BasicTester {
54 | val (cntVal, done) = Counter(true.B, n-1)
55 | val start = 23.U
56 | val sr = ShiftRegister(cntVal + 23.U, n, 1.U, true.B)
57 | when(done) {
58 | assert(sr === 1.U)
59 | stop()
60 | }
61 | }
62 |
63 | class ShiftRegisterSpec extends ChiselPropSpec {
64 | property("ShiftRegister should shift") {
65 | forAll(smallPosInts) { (shift: Int) => assertTesterPasses{ new ShiftTester(shift) } }
66 | }
67 |
68 | property("ShiftRegister should reset all values inside") {
69 | forAll(smallPosInts) { (shift: Int) => assertTesterPasses{ new ShiftResetTester(shift) } }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/stage/phases/Emitter.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.stage.phases
4 |
5 | import firrtl.{AnnotationSeq, EmittedFirrtlCircuit, EmittedFirrtlCircuitAnnotation}
6 | import firrtl.annotations.DeletedAnnotation
7 | import firrtl.options.{Dependency, Phase, StageOptions}
8 | import firrtl.options.Viewer.view
9 |
10 | import chisel3.internal.firrtl.{Emitter => OldEmitter}
11 | import chisel3.stage.{ChiselCircuitAnnotation, ChiselOptions}
12 |
13 | import java.io.{File, FileWriter}
14 |
15 | /** Emit a [[chisel3.stage.ChiselCircuitAnnotation]] to a file if a [[chisel3.stage.ChiselOutputFileAnnotation]] is
16 | * present. A deleted [[firrtl.EmittedFirrtlCircuitAnnotation]] is added.
17 | *
18 | * @todo This should be switched to support correct emission of multiple circuits to multiple files. The API should
19 | * likely mirror how the [[firrtl.stage.phases.Compiler]] parses annotations into "global" annotations and
20 | * left-associative per-circuit annotations.
21 | * @todo The use of the deleted [[firrtl.EmittedFirrtlCircuitAnnotation]] is a kludge to provide some breadcrumbs such
22 | * that the emitted CHIRRTL can be provided back to the old Driver. This should be removed or a better solution
23 | * developed.
24 | */
25 | class Emitter extends Phase {
26 |
27 | override val prerequisites =
28 | Seq( Dependency[Elaborate],
29 | Dependency[AddImplicitOutputFile],
30 | Dependency[AddImplicitOutputAnnotationFile],
31 | Dependency[MaybeAspectPhase] )
32 |
33 | override def optionalPrerequisiteOf = Seq(Dependency[Convert])
34 |
35 | override def invalidates(phase: Phase): Boolean = false
36 |
37 | def transform(annotations: AnnotationSeq): AnnotationSeq = {
38 | val copts = view[ChiselOptions](annotations)
39 | val sopts = view[StageOptions](annotations)
40 |
41 | annotations.flatMap {
42 | case a: ChiselCircuitAnnotation if copts.outputFile.isDefined =>
43 | val file = new File(sopts.getBuildFileName(copts.outputFile.get, Some(".fir")))
44 | val emitted = OldEmitter.emit(a.circuit)
45 | val w = new FileWriter(file)
46 | w.write(emitted)
47 | w.close()
48 | val anno = EmittedFirrtlCircuitAnnotation(EmittedFirrtlCircuit(a.circuit.name, emitted, ".fir"))
49 | Seq(DeletedAnnotation(name, anno), a)
50 | case a => Some(a)
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Util.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | // Useful utilities for tests
4 |
5 | package chiselTests
6 |
7 | import chisel3._
8 | import chisel3.experimental.Interval
9 | import chisel3.internal.firrtl.{IntervalRange, KnownBinaryPoint, Width}
10 | import _root_.firrtl.{ir => firrtlir}
11 |
12 | class PassthroughModuleIO extends Bundle {
13 | val in = Input(UInt(32.W))
14 | val out = Output(UInt(32.W))
15 | }
16 |
17 | trait AbstractPassthroughModule extends RawModule {
18 | val io = IO(new PassthroughModuleIO)
19 | io.out := io.in
20 | }
21 |
22 | class PassthroughModule extends Module with AbstractPassthroughModule
23 | class PassthroughMultiIOModule extends MultiIOModule with AbstractPassthroughModule
24 | class PassthroughRawModule extends RawModule with AbstractPassthroughModule
25 |
26 | case class ScalaIntervalSimulator(intervalRange: IntervalRange) {
27 | val binaryPoint: Int = intervalRange.binaryPoint.asInstanceOf[KnownBinaryPoint].value
28 | val epsilon: Double = 1.0 / math.pow(2.0, binaryPoint.toDouble)
29 |
30 | val (lower, upper) = (intervalRange.lowerBound, intervalRange.upperBound) match {
31 |
32 | case (firrtlir.Closed(lower1), firrtlir.Closed(upper1)) => (lower1, upper1)
33 | case (firrtlir.Closed(lower1), firrtlir.Open(upper1)) => (lower1, upper1 - epsilon)
34 | case (firrtlir.Open(lower1), firrtlir.Closed(upper1)) => (lower1 + epsilon, upper1)
35 | case (firrtlir.Open(lower1), firrtlir.Open(upper1)) => (lower1 + epsilon, upper1 - epsilon)
36 | case _ =>
37 | throw new Exception(s"lower and upper bounds must be defined, range here is $intervalRange")
38 | }
39 |
40 | def clip(value: BigDecimal): BigDecimal = {
41 |
42 | if (value < lower) {
43 | lower
44 | }
45 | else if (value > upper) {
46 | upper
47 | }
48 | else {
49 | value
50 | }
51 | }
52 |
53 | def wrap(value: BigDecimal): BigDecimal = {
54 |
55 | if (value < lower) {
56 | upper + (value - lower) + epsilon
57 | }
58 | else if (value > upper) {
59 | ((value - upper) - epsilon) + lower
60 | }
61 | else {
62 | value
63 | }
64 | }
65 |
66 | def allValues: Iterator[BigDecimal] = {
67 | (lower to upper by epsilon).toIterator
68 | }
69 |
70 | def makeLit(value: BigDecimal): Interval = {
71 | Interval.fromDouble(value.toDouble, width = Width(), binaryPoint = binaryPoint.BP)
72 | }
73 | }
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Counter.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.testers.BasicTester
7 | import chisel3.util._
8 |
9 | class CountTester(max: Int) extends BasicTester {
10 | val cnt = Counter(max)
11 | assert(cnt.n == max)
12 | when(true.B) { cnt.inc() }
13 | val expected = if (max == 0) 0.U else (max - 1).U
14 | when(cnt.value === expected) {
15 | stop()
16 | }
17 | }
18 |
19 | class EnableTester(seed: Int) extends BasicTester {
20 | val ens = RegInit(seed.asUInt)
21 | ens := ens >> 1
22 |
23 | val (cntEnVal, _) = Counter(ens(0), 32)
24 | val (_, done) = Counter(true.B, 33)
25 |
26 | when(done) {
27 | assert(cntEnVal === popCount(seed).asUInt)
28 | stop()
29 | }
30 | }
31 |
32 | class ResetTester(n: Int) extends BasicTester {
33 | val triggerReset = WireInit(false.B)
34 | val wasReset = RegNext(triggerReset)
35 | val (value, _) = Counter(0 until 8, reset = triggerReset)
36 |
37 | triggerReset := value === (n-1).U
38 |
39 | when(wasReset) {
40 | assert(value === 0.U)
41 | stop()
42 | }
43 | }
44 |
45 | class WrapTester(max: Int) extends BasicTester {
46 | val (cnt, wrap) = Counter(true.B, max)
47 | when(wrap) {
48 | assert(cnt === (max - 1).asUInt)
49 | stop()
50 | }
51 | }
52 |
53 | class RangeTester(r: Range) extends BasicTester {
54 | val (cnt, wrap) = Counter(r)
55 | val checkWrap = RegInit(false.B)
56 |
57 | when(checkWrap) {
58 | assert(cnt === r.head.U)
59 | stop()
60 | }.elsewhen(wrap) {
61 | assert(cnt === r.last.U)
62 | checkWrap := true.B
63 | }
64 | }
65 |
66 | class CounterSpec extends ChiselPropSpec {
67 | property("Counter should count up") {
68 | for (i <- 0 until 4) {
69 | assertTesterPasses(new CountTester(i))
70 | }
71 | }
72 |
73 | property("Counter can be en/disabled") {
74 | forAll(safeUInts) { (seed: Int) => whenever(seed >= 0) { assertTesterPasses{ new EnableTester(seed) } } }
75 | }
76 |
77 | property("Counter can be reset") {
78 | forAll(smallPosInts) { (seed: Int) => assertTesterPasses{ new ResetTester(seed) } }
79 | }
80 |
81 | property("Counter should wrap") {
82 | forAll(smallPosInts) { (max: Int) => assertTesterPasses{ new WrapTester(max) } }
83 | }
84 |
85 | property("Counter should handle a range") {
86 | forAll(posRange) { (r: Range) =>
87 | assertTesterPasses{ new RangeTester(r) }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/internal/SourceInfo.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | // This file contains macros for adding source locators at the point of invocation.
4 | //
5 | // This is not part of coreMacros to disallow this macro from being implicitly invoked in Chisel
6 | // frontend (and generating source locators in Chisel core), which is almost certainly a bug.
7 | //
8 | // Note: While these functions and definitions are not private (macros can't be
9 | // private), these are NOT meant to be part of the public API (yet) and no
10 | // forward compatibility guarantees are made.
11 | // A future revision may stabilize the source locator API to allow library
12 | // writers to append source locator information at the point of a library
13 | // function invocation.
14 |
15 | package chisel3.internal.sourceinfo
16 |
17 | import scala.language.experimental.macros
18 | import scala.reflect.macros.blackbox.Context
19 |
20 | /** Abstract base class for generalized source information.
21 | */
22 | sealed trait SourceInfo {
23 | /** A prettier toString
24 | *
25 | * Make a useful message if SourceInfo is available, nothing otherwise
26 | */
27 | def makeMessage(f: String => String): String
28 | }
29 |
30 | sealed trait NoSourceInfo extends SourceInfo {
31 | def makeMessage(f: String => String): String = ""
32 | }
33 |
34 | /** For when source info can't be generated because of a technical limitation, like for Reg because
35 | * Scala macros don't support named or default arguments.
36 | */
37 | case object UnlocatableSourceInfo extends NoSourceInfo
38 |
39 | /** For when source info isn't generated because the function is deprecated and we're lazy.
40 | */
41 | case object DeprecatedSourceInfo extends NoSourceInfo
42 |
43 | /** For FIRRTL lines from a Scala source line.
44 | */
45 | case class SourceLine(filename: String, line: Int, col: Int) extends SourceInfo {
46 | def makeMessage(f: String => String): String = f(s"@[$filename $line:$col]")
47 | }
48 |
49 | /** Provides a macro that returns the source information at the invocation point.
50 | */
51 | object SourceInfoMacro {
52 | def generate_source_info(c: Context): c.Tree = {
53 | import c.universe._
54 | val p = c.enclosingPosition
55 | q"_root_.chisel3.internal.sourceinfo.SourceLine(${p.source.file.name}, ${p.line}, ${p.column})"
56 | }
57 | }
58 |
59 | object SourceInfo {
60 | implicit def materialize: SourceInfo = macro SourceInfoMacro.generate_source_info
61 | }
62 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/State.scala:
--------------------------------------------------------------------------------
1 | /* Version 0.1 Last updated: 6/30/2020 */
2 | package chisel3
3 |
4 | import scala.collection.immutable.ListMap
5 | import scala.collection.mutable.{ArrayBuffer, HashMap}
6 | import scala.collection.JavaConversions._
7 | import scala.language.experimental.macros
8 |
9 | import java.util.IdentityHashMap
10 | import chisel3.internal._
11 | import chisel3.internal.Builder._
12 | import chisel3.internal.firrtl._
13 | import chisel3.internal.sourceinfo.{InstTransform, SourceInfo}
14 | import chisel3.experimental.BaseModule
15 | import _root_.firrtl.annotations.{ModuleName, ModuleTarget, IsModule}
16 | import chisel3.internal.sourceinfo.UnlocatableSourceInfo
17 | import chisel3.twine._
18 |
19 | /** Abstract base class for State, which only contains basic sequential blocks.
20 | * These may contain both logic and state which are written in the Module
21 | * body (constructor).
22 | * This abstract base class includes an implicit clock and reset.
23 | *
24 | * @note State instantiations must be wrapped in a State() call.
25 | */
26 | abstract class State(implicit moduleCompileOptions: CompileOptions)
27 | extends MultiIOModule {
28 |
29 | private[chisel3] override def generateComponent(): Component = { // scalastyle:ignore cyclomatic.complexity
30 | val component = super.generateComponent
31 |
32 | var containsReg = false
33 | // State instance must contain registers
34 | for(command <- getCommands){
35 | command match{
36 | case reg: DefReg => (containsReg = true)
37 | case regInit: DefRegInit => (containsReg = true)
38 | case _ => ()
39 | }
40 | }
41 | if(!containsReg){
42 | throwException("State class must contain Reg/RegNext/RegInit")
43 | }
44 |
45 | component
46 | }
47 | }
48 |
49 | object State extends SourceInfoDoc {
50 | /** A wrapper method that all State instantiations must be wrapped in
51 | * (necessary to help Chisel track internal state).
52 | *
53 | * @param bc the Module being created
54 | *
55 | * @return the input module `m` with Chisel metadata properly set
56 | */
57 | def apply[T <: BaseModule](bc: => T): T = macro InstTransform.apply[T]
58 |
59 | /** @group SourceInfoTransformMacro */
60 | def do_apply[T <: BaseModule](bc: => T)
61 | (implicit sourceInfo: SourceInfo,
62 | compileOptions: CompileOptions): T = Module.do_apply(bc)(sourceInfo,compileOptions)
63 | }
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage.phases
4 |
5 |
6 | import chisel3.RawModule
7 | import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselOutputFileAnnotation}
8 | import chisel3.stage.phases.{Convert, Elaborate, Emitter}
9 |
10 | import firrtl.{AnnotationSeq, EmittedFirrtlCircuitAnnotation}
11 | import firrtl.annotations.DeletedAnnotation
12 | import firrtl.options.{Phase, TargetDirAnnotation}
13 |
14 | import java.io.File
15 | import org.scalatest.flatspec.AnyFlatSpec
16 | import org.scalatest.matchers.should.Matchers
17 |
18 | class EmitterSpec extends AnyFlatSpec with Matchers {
19 |
20 | class FooModule extends RawModule { override val desiredName = "Foo" }
21 | class BarModule extends RawModule { override val desiredName = "Bar" }
22 |
23 | class Fixture { val phase: Phase = new Emitter }
24 |
25 | behavior of classOf[Emitter].toString
26 |
27 | it should "do nothing if no ChiselOutputFileAnnotations are present" in new Fixture {
28 | val dir = new File("test_run_dir/EmitterSpec")
29 | val annotations = (new Elaborate).transform(Seq( TargetDirAnnotation(dir.toString),
30 | ChiselGeneratorAnnotation(() => new FooModule) ))
31 | val annotationsx = phase.transform(annotations)
32 |
33 | val Seq(fooFile, barFile) = Seq("Foo.fir", "Bar.fir").map(f => new File(dir + "/" + f))
34 |
35 | info(s"$fooFile does not exist")
36 | fooFile should not (exist)
37 |
38 | info("annotations are unmodified")
39 | annotationsx.toSeq should be (annotations.toSeq)
40 | }
41 |
42 | it should "emit a ChiselCircuitAnnotation to a specific file" in new Fixture {
43 | val dir = new File("test_run_dir/EmitterSpec")
44 | val circuit = (new Elaborate)
45 | .transform(Seq(ChiselGeneratorAnnotation(() => new BarModule)))
46 | .collectFirst{ case a: ChiselCircuitAnnotation => a}
47 | .get
48 | val annotations = phase.transform(Seq( TargetDirAnnotation(dir.toString),
49 | circuit,
50 | ChiselOutputFileAnnotation("Baz") ))
51 |
52 | val bazFile = new File(dir + "/Baz.fir")
53 |
54 | info(s"$bazFile exists")
55 | bazFile should (exist)
56 |
57 | info("a deleted EmittedFirrtlCircuitAnnotation should be generated")
58 | annotations.collect{ case a @ DeletedAnnotation(_, _: EmittedFirrtlCircuitAnnotation) => a }.size should be (1)
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/Element.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3
4 |
5 | import chisel3.internal.Builder.pushCommand
6 | import chisel3.internal.firrtl._
7 | import chisel3.internal.sourceinfo.SourceInfo
8 | import chisel3.internal._
9 |
10 | /** Element is a leaf data type: it cannot contain other [[Data]] objects. Example uses are for representing primitive
11 | * data types, like integers and bits.
12 | *
13 | * @define coll element
14 | */
15 | abstract class Element extends Data {
16 | private[chisel3] final def allElements: Seq[Element] = Seq(this)
17 | def widthKnown: Boolean = width.known
18 | def name: String = getRef.name
19 |
20 | private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) {
21 | binding = target
22 | val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection)
23 | direction = ActualDirection.fromSpecified(resolvedDirection)
24 | }
25 |
26 | private[chisel3] override def topBindingOpt: Option[TopBinding] = super.topBindingOpt match {
27 | // Translate Bundle lit bindings to Element lit bindings
28 | case Some(BundleLitBinding(litMap)) => litMap.get(this) match {
29 | case Some(litArg) => Some(ElementLitBinding(litArg))
30 | case _ => Some(DontCareBinding())
31 | }
32 | case topBindingOpt => topBindingOpt
33 | }
34 |
35 | private[chisel3] def litArgOption: Option[LitArg] = topBindingOpt match {
36 | case Some(ElementLitBinding(litArg)) => Some(litArg)
37 | case _ => None
38 | }
39 |
40 | override def litOption: Option[BigInt] = litArgOption.map(_.num)
41 | private[chisel3] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth)
42 |
43 | // provide bits-specific literal handling functionality here
44 | override def ref: Arg = topBindingOpt match {
45 | case Some(ElementLitBinding(litArg)) => litArg
46 | case Some(BundleLitBinding(litMap)) => litMap.get(this) match {
47 | case Some(litArg) => litArg
48 | case _ => throwException(s"internal error: DontCare should be caught before getting ref")
49 | }
50 | case _ => super.ref
51 | }
52 |
53 | private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
54 | // If the source is a DontCare, generate a DefInvalid for the sink,
55 | // otherwise, issue a Connect.
56 | if (that == DontCare) {
57 | pushCommand(DefInvalid(sourceInfo, Node(this)))
58 | } else {
59 | pushCommand(Connect(sourceInfo, Node(this), that.ref))
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/experimental/ProgrammaticPortsSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 | package experimental
5 |
6 | import chisel3._
7 | import chisel3.stage.ChiselStage
8 |
9 | // NOTE This is currently an experimental API and subject to change
10 | // Example using a private port
11 | class PrivatePort extends NamedModuleTester {
12 | private val port = expectName(IO(Input(UInt(8.W))), "foo")
13 | port.suggestName("foo")
14 | }
15 |
16 | // Example of using composition to add ports to a Module
17 | class CompositionalPort(module: NamedModuleTester, name: String) {
18 | import chisel3.experimental.IO
19 | val foo = module.expectName(IO(Output(Bool())), name)
20 | foo.suggestName(name)
21 | foo := true.B
22 | }
23 |
24 | class CompositionalPortTester extends NamedModuleTester {
25 | val a = new CompositionalPort(this, "cheese")
26 | val b = new CompositionalPort(this, "tart")
27 | }
28 |
29 | class PortsWinTester extends NamedModuleTester {
30 | val wire = expectName(Wire(UInt()), "wire_1")
31 | val foo = expectName(Wire(UInt()).suggestName("wire"), "wire_2")
32 | val output = expectName(IO(Output(UInt())).suggestName("wire"), "wire")
33 | }
34 |
35 | class ProgrammaticPortsSpec extends ChiselFlatSpec with Utils {
36 |
37 | private def doTest(testMod: => NamedModuleTester): Unit = {
38 | var module: NamedModuleTester = null
39 | ChiselStage.elaborate { module = testMod; module }
40 | assert(module.getNameFailures() == Nil)
41 | }
42 |
43 | "Programmatic port creation" should "be supported" in {
44 | doTest(new PrivatePort)
45 | }
46 |
47 | "Calling IO outside of a Module definition" should "be supported" in {
48 | doTest(new CompositionalPortTester)
49 | }
50 |
51 | "Ports" should "always win over internal components in naming" in {
52 | doTest(new PortsWinTester)
53 | }
54 |
55 | "LegacyModule" should "ignore suggestName on ports" in {
56 | doTest(new Module with NamedModuleTester {
57 | val io = IO(new Bundle {
58 | val foo = Output(UInt(8.W))
59 | })
60 | expectName(io.suggestName("cheese"), "io")
61 | expectName(clock.suggestName("tart"), "clock")
62 | expectName(reset.suggestName("teser"), "reset")
63 | })
64 | }
65 |
66 | "SuggestName collisions on ports" should "be illegal" in {
67 | a [ChiselException] should be thrownBy extractCause[ChiselException] {
68 | ChiselStage.elaborate(new MultiIOModule {
69 | val foo = IO(UInt(8.W)).suggestName("apple")
70 | val bar = IO(UInt(8.W)).suggestName("apple")
71 | })
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/twine/hardfloat/recFNFromFN.scala:
--------------------------------------------------------------------------------
1 |
2 | /*============================================================================
3 |
4 | This Chisel source file is part of a pre-release version of the HardFloat IEEE
5 | Floating-Point Arithmetic Package, by John R. Hauser (with some contributions
6 | from Yunsup Lee and Andrew Waterman, mainly concerning testing).
7 |
8 | Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the
9 | University of California. All rights reserved.
10 |
11 | Redistribution and use in source and binary forms, with or without
12 | modification, are permitted provided that the following conditions are met:
13 |
14 | 1. Redistributions of source code must retain the above copyright notice,
15 | this list of conditions, and the following disclaimer.
16 |
17 | 2. Redistributions in binary form must reproduce the above copyright notice,
18 | this list of conditions, and the following disclaimer in the documentation
19 | and/or other materials provided with the distribution.
20 |
21 | 3. Neither the name of the University nor the names of its contributors may
22 | be used to endorse or promote products derived from this software without
23 | specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
26 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
28 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 | =============================================================================*/
37 |
38 | package chisel3.twine.hardfloat
39 |
40 | import Chisel._
41 |
42 | object recFNFromFN
43 | {
44 | def apply(expWidth: Int, sigWidth: Int, in: Bits) =
45 | {
46 | val rawIn = rawFloatFromFN(expWidth, sigWidth, in)
47 | Cat(rawIn.sign,
48 | Mux(rawIn.isZero, Bits(0, 3), rawIn.sExp(expWidth, expWidth - 2)) |
49 | Mux(rawIn.isNaN, UInt(1), UInt(0)),
50 | rawIn.sExp(expWidth - 3, 0),
51 | rawIn.sig(sigWidth - 2, 0)
52 | )
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Harness.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import java.io.File
6 |
7 | import firrtl.util.BackendCompilationUtilities
8 |
9 | class HarnessSpec extends ChiselPropSpec
10 | with BackendCompilationUtilities {
11 |
12 | def makeTrivialVerilog: (File => File) = makeHarness((prefix: String) => s"""
13 | module ${prefix};
14 | initial begin
15 | $$display("$prefix!");
16 | $$finish;
17 | end
18 | endmodule
19 | """, ".v") _
20 |
21 | def makeFailingVerilog: (File => File) = makeHarness((prefix: String) => s"""
22 | module $prefix;
23 | initial begin
24 | assert (1 == 0) else $$error("My specific, expected error message!");
25 | $$display("$prefix!");
26 | $$finish;
27 | end
28 | endmodule
29 | """, ".v") _
30 |
31 | def makeCppHarness: (File => File) = makeHarness((prefix: String) => s"""
32 | #include "V$prefix.h"
33 | #include "verilated.h"
34 |
35 | vluint64_t main_time = 0;
36 | double sc_time_stamp () { return main_time; }
37 |
38 | int main(int argc, char **argv, char **env) {
39 | Verilated::commandArgs(argc, argv);
40 | V${prefix}* top = new V${prefix};
41 | while (!Verilated::gotFinish()) { top->eval(); }
42 | delete top;
43 | exit(0);
44 | }
45 |
46 | void vl_finish(const char* filename, int linenum, const char* hier) {
47 | Verilated::flushCall();
48 | exit(0);
49 | }
50 | """, ".cpp") _
51 |
52 | /** Compiles a C++ emulator from Verilog and returns the path to the
53 | * executable and the executable filename as a tuple.
54 | */
55 | def simpleHarnessBackend(make: File => File): (File, String) = {
56 | val target = "test"
57 | val path = createTestDirectory(target)
58 | val fname = new File(path, target)
59 |
60 | val cppHarness = makeCppHarness(fname)
61 |
62 | make(fname)
63 | verilogToCpp(target, path, Seq(), cppHarness).!
64 | cppToExe(target, path).!
65 | (path, target)
66 | }
67 |
68 | property("Test making trivial verilog harness and executing") {
69 | val (path, target) = simpleHarnessBackend(makeTrivialVerilog)
70 |
71 | assert(executeExpectingSuccess(target, path))
72 | }
73 |
74 | property("Test that assertion failues in Verilog are caught") {
75 | val (path, target) = simpleHarnessBackend(makeFailingVerilog)
76 |
77 | assert(!executeExpectingSuccess(target, path))
78 | assert(executeExpectingFailure(target, path))
79 | assert(executeExpectingFailure(target, path, "My specific, expected error message!"))
80 | assert(!executeExpectingFailure(target, path, "A string that doesn't match any test output"))
81 | }
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/ExtModule.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.experimental._
7 | import chisel3.stage.ChiselStage
8 | import chisel3.testers.{BasicTester, TesterDriver}
9 |
10 | // Avoid collisions with regular BlackBox tests by putting ExtModule blackboxes
11 | // in their own scope.
12 | package ExtModule {
13 |
14 | import chisel3.experimental.ExtModule
15 |
16 | class BlackBoxInverter extends ExtModule {
17 | val in = IO(Input(Bool()))
18 | val out = IO(Output(Bool()))
19 | }
20 |
21 | class BlackBoxPassthrough extends ExtModule {
22 | val in = IO(Input(Bool()))
23 | val out = IO(Output(Bool()))
24 | }
25 | }
26 |
27 | class ExtModuleTester extends BasicTester {
28 | val blackBoxPos = Module(new ExtModule.BlackBoxInverter)
29 | val blackBoxNeg = Module(new ExtModule.BlackBoxInverter)
30 |
31 | blackBoxPos.in := 1.U
32 | blackBoxNeg.in := 0.U
33 |
34 | assert(blackBoxNeg.out === 1.U)
35 | assert(blackBoxPos.out === 0.U)
36 | stop()
37 | }
38 |
39 | /** Instantiate multiple BlackBoxes with similar interfaces but different
40 | * functionality. Used to detect failures in BlackBox naming and module
41 | * deduplication.
42 | */
43 |
44 | class MultiExtModuleTester extends BasicTester {
45 | val blackBoxInvPos = Module(new ExtModule.BlackBoxInverter)
46 | val blackBoxInvNeg = Module(new ExtModule.BlackBoxInverter)
47 | val blackBoxPassPos = Module(new ExtModule.BlackBoxPassthrough)
48 | val blackBoxPassNeg = Module(new ExtModule.BlackBoxPassthrough)
49 |
50 | blackBoxInvPos.in := 1.U
51 | blackBoxInvNeg.in := 0.U
52 | blackBoxPassPos.in := 1.U
53 | blackBoxPassNeg.in := 0.U
54 |
55 | assert(blackBoxInvNeg.out === 1.U)
56 | assert(blackBoxInvPos.out === 0.U)
57 | assert(blackBoxPassNeg.out === 0.U)
58 | assert(blackBoxPassPos.out === 1.U)
59 | stop()
60 | }
61 |
62 | class ExtModuleSpec extends ChiselFlatSpec {
63 | "A ExtModule inverter" should "work" in {
64 | assertTesterPasses({ new ExtModuleTester },
65 | Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly)
66 | }
67 | "Multiple ExtModules" should "work" in {
68 | assertTesterPasses({ new MultiExtModuleTester },
69 | Seq("/chisel3/BlackBoxTest.v"), TesterDriver.verilatorOnly)
70 | }
71 | "DataMirror.modulePorts" should "work with ExtModule" in {
72 | ChiselStage.elaborate(new Module {
73 | val io = IO(new Bundle { })
74 | val m = Module(new ExtModule.BlackBoxPassthrough)
75 | assert(DataMirror.modulePorts(m) == Seq(
76 | "in" -> m.in, "out" -> m.out))
77 | })
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage.phases
4 |
5 |
6 | import chisel3._
7 | import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform}
8 | import chisel3.stage.ChiselGeneratorAnnotation
9 | import chisel3.stage.phases.{Convert, Elaborate}
10 |
11 | import firrtl.{AnnotationSeq, CircuitForm, CircuitState, DependencyAPIMigration, Transform, UnknownForm}
12 | import firrtl.annotations.{Annotation, NoTargetAnnotation}
13 | import firrtl.options.Phase
14 | import firrtl.stage.{FirrtlCircuitAnnotation, RunFirrtlTransformAnnotation}
15 | import org.scalatest.flatspec.AnyFlatSpec
16 | import org.scalatest.matchers.should.Matchers
17 |
18 | class ConvertSpecFirrtlTransform extends Transform with DependencyAPIMigration {
19 | override def prerequisites = Seq.empty
20 | override def optionalPrerequisites = Seq.empty
21 | override def optionalPrerequisiteOf = Seq.empty
22 | override def invalidates(a: Transform) = false
23 | def execute(state: CircuitState): CircuitState = state
24 | }
25 |
26 | case class ConvertSpecFirrtlAnnotation(name: String) extends NoTargetAnnotation
27 |
28 | case class ConvertSpecChiselAnnotation(name: String) extends ChiselAnnotation with RunFirrtlTransform {
29 | def toFirrtl: Annotation = ConvertSpecFirrtlAnnotation(name)
30 | def transformClass: Class[_ <: Transform] = classOf[ConvertSpecFirrtlTransform]
31 | }
32 |
33 | class ConvertSpecFoo extends RawModule {
34 | override val desiredName: String = "foo"
35 |
36 | val in = IO(Input(Bool()))
37 | val out = IO(Output(Bool()))
38 |
39 | experimental.annotate(ConvertSpecChiselAnnotation("bar"))
40 | }
41 |
42 | class ConvertSpec extends AnyFlatSpec with Matchers {
43 |
44 | class Fixture { val phase: Phase = new Convert }
45 |
46 | behavior of classOf[Convert].toString
47 |
48 | it should "convert a Chisel Circuit to a FIRRTL Circuit" in new Fixture {
49 | val annos: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new ConvertSpecFoo))
50 |
51 | val annosx = Seq(new Elaborate, phase)
52 | .foldLeft(annos)( (a, p) => p.transform(a) )
53 |
54 | info("FIRRTL circuit generated")
55 | annosx.collect{ case a: FirrtlCircuitAnnotation => a.circuit.main }.toSeq should be (Seq("foo"))
56 |
57 | info("FIRRTL annotations generated")
58 | annosx.collect{ case a: ConvertSpecFirrtlAnnotation => a.name }.toSeq should be (Seq("bar"))
59 |
60 | info("FIRRTL transform annotations generated")
61 | annosx.collect{ case a: RunFirrtlTransformAnnotation => a.transform.getClass}
62 | .toSeq should be (Seq(classOf[ConvertSpecFirrtlTransform]))
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/DedupSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.util._
7 |
8 | class DedupIO extends Bundle {
9 | val in = Flipped(Decoupled(UInt(32.W)))
10 | val out = Decoupled(UInt(32.W))
11 | }
12 |
13 | class DedupQueues(n: Int) extends Module {
14 | require(n > 0)
15 | val io = IO(new DedupIO)
16 | val queues = Seq.fill(n)(Module(new Queue(UInt(32.W), 4)))
17 | var port = io.in
18 | for (q <- queues) {
19 | q.io.enq <> port
20 | port = q.io.deq
21 | }
22 | io.out <> port
23 | }
24 |
25 | /* This module creates a Queue in a nested function (such that it is not named via reflection). The
26 | * default naming for instances prior to #470 caused otherwise identical instantiations of this
27 | * module to have different instance names for the queues which prevented deduplication.
28 | * NestedDedup instantiates this module twice to ensure it is deduplicated properly.
29 | */
30 | class DedupSubModule extends Module {
31 | val io = IO(new DedupIO)
32 | io.out <> Queue(io.in, 4)
33 | }
34 |
35 | class NestedDedup extends Module {
36 | val io = IO(new DedupIO)
37 | val inst0 = Module(new DedupSubModule)
38 | val inst1 = Module(new DedupSubModule)
39 | inst0.io.in <> io.in
40 | inst1.io.in <> inst0.io.out
41 | io.out <> inst1.io.out
42 | }
43 |
44 | object DedupConsts {
45 | val foo = 3.U
46 | }
47 |
48 | class SharedConstantValDedup extends Module {
49 | val io = IO(new Bundle {
50 | val in = Input(UInt(8.W))
51 | val out = Output(UInt(8.W))
52 | })
53 | io.out := io.in + DedupConsts.foo
54 | }
55 |
56 | class SharedConstantValDedupTop extends Module {
57 | val io = IO(new Bundle {
58 | val in = Input(UInt(8.W))
59 | val out = Output(UInt(8.W))
60 | })
61 | val inst0 = Module(new SharedConstantValDedup)
62 | val inst1 = Module(new SharedConstantValDedup)
63 | inst0.io.in := io.in
64 | inst1.io.in := io.in
65 | io.out := inst0.io.out + inst1.io.out
66 | }
67 |
68 |
69 | class DedupSpec extends ChiselFlatSpec {
70 | private val ModuleRegex = """\s*module\s+(\w+)\b.*""".r
71 | def countModules(verilog: String): Int =
72 | (verilog split "\n" collect { case ModuleRegex(name) => name }).size
73 |
74 | "Deduplication" should "occur" in {
75 | assert(countModules(compile { new DedupQueues(4) }) === 2)
76 | }
77 |
78 | it should "properly dedup modules with deduped submodules" in {
79 | assert(countModules(compile { new NestedDedup }) === 3)
80 | }
81 |
82 | it should "dedup modules that share a literal" in {
83 | assert(countModules(compile { new SharedConstantValDedupTop }) === 2)
84 | }
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/Assert.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 | import chisel3.testers.BasicTester
8 | import chisel3.util._
9 |
10 | class FailingAssertTester() extends BasicTester {
11 | assert(false.B)
12 | // Wait to come out of reset
13 | val (_, done) = Counter(!reset.asBool, 4)
14 | when (done) {
15 | stop()
16 | }
17 | }
18 |
19 | class SucceedingAssertTester() extends BasicTester {
20 | assert(true.B)
21 | // Wait to come out of reset
22 | val (_, done) = Counter(!reset.asBool, 4)
23 | when (done) {
24 | stop()
25 | }
26 | }
27 |
28 | class PipelinedResetModule extends Module {
29 | val io = IO(new Bundle { })
30 | val a = RegInit(0xbeef.U)
31 | val b = RegInit(0xbeef.U)
32 | assert(a === b)
33 | }
34 |
35 | // This relies on reset being asserted for 3 or more cycles
36 | class PipelinedResetTester extends BasicTester {
37 | val module = Module(new PipelinedResetModule)
38 |
39 | module.reset := RegNext(RegNext(RegNext(reset)))
40 |
41 | val (_, done) = Counter(!reset.asBool, 4)
42 | when (done) {
43 | stop()
44 | }
45 | }
46 |
47 | class ModuloAssertTester extends BasicTester {
48 | assert((4.U % 2.U) === 0.U)
49 | stop()
50 | }
51 |
52 | class FormattedAssertTester extends BasicTester {
53 | val foobar = Wire(UInt(32.W))
54 | foobar := 123.U
55 | assert(foobar === 123.U, "Error! Wire foobar =/= %x! This is 100%% wrong.\n", foobar)
56 | stop()
57 | }
58 |
59 | class BadUnescapedPercentAssertTester extends BasicTester {
60 | assert(1.U === 1.U, "I'm 110% sure this is an invalid message")
61 | stop()
62 | }
63 |
64 | class AssertSpec extends ChiselFlatSpec with Utils {
65 | "A failing assertion" should "fail the testbench" in {
66 | assert(!runTester{ new FailingAssertTester })
67 | }
68 | "A succeeding assertion" should "not fail the testbench" in {
69 | assertTesterPasses{ new SucceedingAssertTester }
70 | }
71 | "An assertion" should "not assert until we come out of reset" in {
72 | assertTesterPasses{ new PipelinedResetTester }
73 | }
74 | "Assertions" should "allow the modulo operator % in the message" in {
75 | assertTesterPasses{ new ModuloAssertTester }
76 | }
77 | they should "allow printf-style format strings with arguments" in {
78 | assertTesterPasses{ new FormattedAssertTester }
79 | }
80 | they should "not allow unescaped % in the message" in {
81 | a [java.util.UnknownFormatConversionException] should be thrownBy {
82 | extractCause[java.util.UnknownFormatConversionException] {
83 | ChiselStage.elaborate { new BadUnescapedPercentAssertTester }
84 | }
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/Logic.scala:
--------------------------------------------------------------------------------
1 | /* Version 0.1 Last updated: 6/30/2020 */
2 | package chisel3
3 |
4 | import scala.collection.immutable.ListMap
5 | import scala.collection.mutable.{ArrayBuffer, HashMap}
6 | import scala.collection.JavaConversions._
7 | import scala.language.experimental.macros
8 |
9 | import java.util.IdentityHashMap
10 | import chisel3.internal._
11 | import chisel3.internal.Builder._
12 | import chisel3.internal.firrtl._
13 | import chisel3.internal.sourceinfo.{InstTransform, SourceInfo}
14 | import chisel3.experimental.BaseModule
15 | import _root_.firrtl.annotations.{ModuleName, ModuleTarget, IsModule}
16 | import chisel3.internal.sourceinfo.UnlocatableSourceInfo
17 | import chisel3.twine._
18 |
19 | /** Abstract base class for Logic, which only contains basic combinational blocks.
20 | * These may contain logic which are written in the Module
21 | * body (constructor).
22 | * This abstract base class includes an implicit clock and reset.
23 | *
24 | * @note Logic instantiations must be wrapped in a Logic() call.
25 | */
26 | abstract class Logic(implicit moduleCompileOptions: CompileOptions)
27 | extends MultiIOModule {
28 |
29 | private[chisel3] override def generateComponent(): Component = { // scalastyle:ignore cyclomatic.complexity
30 | val component = super.generateComponent
31 |
32 | // Logic instance does not contain any registers
33 | for(command <- getCommands){
34 | command match{
35 | case reg: DefReg => throwException("Logic class cannot contain Reg")
36 | case regInit: DefRegInit => throwException("Logic class cannot contain RegInit")
37 | case defMemory: DefMemory => throwException("Logic class cannot contain Memory")
38 | case defSeqMemory: DefSeqMemory => throwException("Logic class cannot contain SeqMemory")
39 | case defMemPort: DefMemPort[t] => throwException("Logic class cannot contain Memport")
40 | case _ => ()
41 | }
42 | }
43 |
44 | component
45 | }
46 | }
47 |
48 | object Logic extends SourceInfoDoc {
49 | /** A wrapper method that all Logic instantiations must be wrapped in
50 | * (necessary to help Chisel track internal state).
51 | *
52 | * @param bc the Module being created
53 | *
54 | * @return the input module `m` with Chisel metadata properly set
55 | */
56 | def apply[T <: BaseModule](bc: => T): T = macro InstTransform.apply[T]
57 |
58 | /** @group SourceInfoTransformMacro */
59 | def do_apply[T <: BaseModule](bc: => T)
60 | (implicit sourceInfo: SourceInfo,
61 | compileOptions: CompileOptions): T = Module.do_apply(bc)(sourceInfo,compileOptions)
62 | }
--------------------------------------------------------------------------------
/src/main/scala/chisel3/util/OneHot.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | /** Circuit generators for working with one-hot representations.
4 | */
5 |
6 | package chisel3.util
7 |
8 | import chisel3._
9 |
10 | /** Returns the bit position of the sole high bit of the input bitvector.
11 | *
12 | * Inverse operation of [[UIntToOH]].
13 | *
14 | * @example {{{
15 | * OHToUInt("b0100".U) // results in 2.U
16 | * }}}
17 | *
18 | * @note assumes exactly one high bit, results undefined otherwise
19 | */
20 | object OHToUInt {
21 | def apply(in: Seq[Bool]): UInt = apply(Cat(in.reverse), in.size)
22 | def apply(in: Vec[Bool]): UInt = apply(in.asUInt, in.size)
23 | def apply(in: Bits): UInt = apply(in, in.getWidth)
24 |
25 | def apply(in: Bits, width: Int): UInt = {
26 | if (width <= 2) {
27 | Log2(in, width)
28 | } else {
29 | val mid = 1 << (log2Ceil(width)-1)
30 | val hi = in(width-1, mid)
31 | val lo = in(mid-1, 0)
32 | Cat(hi.orR, apply(hi | lo, mid))
33 | }
34 | }
35 | }
36 |
37 | /** Returns the bit position of the least-significant high bit of the input bitvector.
38 | *
39 | * @example {{{
40 | * PriorityEncoder("b0110".U) // results in 1.U
41 | * }}}
42 | *
43 | * Multiple bits may be high in the input.
44 | */
45 | object PriorityEncoder {
46 | def apply(in: Seq[Bool]): UInt = PriorityMux(in, (0 until in.size).map(_.asUInt))
47 | def apply(in: Bits): UInt = apply(in.asBools)
48 | }
49 |
50 | /** Returns the one hot encoding of the input UInt.
51 | *
52 | * @example {{{
53 | * UIntToOH(2.U) // results in "b0100".U
54 | * }}}
55 | *
56 | */
57 | object UIntToOH {
58 | def apply(in: UInt): UInt = 1.U << in
59 | def apply(in: UInt, width: Int): UInt = width match {
60 | case 0 => 0.U(0.W)
61 | case 1 => 1.U(1.W)
62 | case _ =>
63 | val shiftAmountWidth = log2Ceil(width)
64 | val shiftAmount = in.pad(shiftAmountWidth)(shiftAmountWidth - 1, 0)
65 | (1.U << shiftAmount)(width - 1, 0)
66 | }
67 | }
68 |
69 | /** Returns a bit vector in which only the least-significant 1 bit in the input vector, if any,
70 | * is set.
71 | *
72 | * @example {{{
73 | * PriorityEncoderOH(Seq(false.B, true.B, true.B, false.B)) // results in Seq(false.B, true.B, false.B, false.B)
74 | * }}}
75 | */
76 | object PriorityEncoderOH {
77 | private def encode(in: Seq[Bool]): UInt = {
78 | val outs = Seq.tabulate(in.size)(i => (BigInt(1) << i).asUInt(in.size.W))
79 | PriorityMux(in :+ true.B, outs :+ 0.U(in.size.W))
80 | }
81 | def apply(in: Seq[Bool]): Seq[Bool] = {
82 | val enc = encode(in)
83 | Seq.tabulate(in.size)(enc(_))
84 | }
85 | def apply(in: Bits): UInt = encode((0 until in.getWidth).map(i => in(i)))
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/RawModuleSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 | import chisel3.testers.BasicTester
8 |
9 | class UnclockedPlusOne extends RawModule {
10 | val in = IO(Input(UInt(32.W)))
11 | val out = IO(Output(UInt(32.W)))
12 |
13 | out := in + 1.asUInt
14 | }
15 |
16 | class RawModuleTester extends BasicTester {
17 | val plusModule = Module(new UnclockedPlusOne)
18 | plusModule.in := 42.U
19 | assert(plusModule.out === 43.U)
20 | stop()
21 | }
22 |
23 | class PlusOneModule extends Module {
24 | val io = IO(new Bundle {
25 | val in = Input(UInt(32.W))
26 | val out = Output(UInt(32.W))
27 | })
28 | io.out := io.in + 1.asUInt
29 | }
30 |
31 | class RawModuleWithImplicitModule extends RawModule {
32 | val in = IO(Input(UInt(32.W)))
33 | val out = IO(Output(UInt(32.W)))
34 | val clk = IO(Input(Clock()))
35 | val rst = IO(Input(Bool()))
36 |
37 | withClockAndReset(clk, rst) {
38 | val plusModule = Module(new PlusOneModule)
39 | plusModule.io.in := in
40 | out := plusModule.io.out
41 | }
42 | }
43 |
44 | class ImplicitModuleInRawModuleTester extends BasicTester {
45 | val plusModule = Module(new RawModuleWithImplicitModule)
46 | plusModule.clk := clock
47 | plusModule.rst := reset
48 | plusModule.in := 42.U
49 | assert(plusModule.out === 43.U)
50 | stop()
51 | }
52 |
53 | class RawModuleWithDirectImplicitModule extends RawModule {
54 | val plusModule = Module(new PlusOneModule)
55 | }
56 |
57 | class ImplicitModuleDirectlyInRawModuleTester extends BasicTester {
58 | val plusModule = Module(new RawModuleWithDirectImplicitModule)
59 | stop()
60 | }
61 |
62 | class RawModuleSpec extends ChiselFlatSpec with Utils {
63 | "RawModule" should "elaborate" in {
64 | ChiselStage.elaborate { new RawModuleWithImplicitModule }
65 | }
66 |
67 | "RawModule" should "work" in {
68 | assertTesterPasses({ new RawModuleTester })
69 | }
70 |
71 | "ImplicitModule in a withClock block in a RawModule" should "work" in {
72 | assertTesterPasses({ new ImplicitModuleInRawModuleTester })
73 | }
74 |
75 |
76 | "ImplicitModule directly in a RawModule" should "fail" in {
77 | intercept[chisel3.internal.ChiselException] {
78 | extractCause[ChiselException] {
79 | ChiselStage.elaborate { new RawModuleWithDirectImplicitModule }
80 | }
81 | }
82 | }
83 |
84 | "ImplicitModule directly in a RawModule in an ImplicitModule" should "fail" in {
85 | intercept[chisel3.internal.ChiselException] {
86 | extractCause[ChiselException] {
87 | ChiselStage.elaborate { new ImplicitModuleDirectlyInRawModuleTester }
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.stage
4 |
5 | import chisel3._
6 | import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, DesignAnnotation}
7 | import firrtl.options.OptionsException
8 | import org.scalatest.flatspec.AnyFlatSpec
9 | import org.scalatest.matchers.should.Matchers
10 |
11 | class ChiselAnnotationsSpecFoo extends RawModule {
12 | val in = IO(Input(Bool()))
13 | val out = IO(Output(Bool()))
14 | out := ~in
15 | }
16 |
17 | class ChiselAnnotationsSpecBaz(name: String) extends ChiselAnnotationsSpecFoo {
18 | override val desiredName = name
19 | }
20 |
21 | class ChiselAnnotationsSpecQux extends ChiselAnnotationsSpecFoo {
22 | /* This printf requires an implicit clock and reset, but RawModule has none. This will thereby fail elaboration. */
23 | printf("hello")
24 | }
25 |
26 | class ChiselAnnotation
27 |
28 | class ChiselAnnotationsSpec extends AnyFlatSpec with Matchers {
29 |
30 | behavior of "ChiselGeneratorAnnotation elaboration"
31 |
32 | it should "elaborate to a ChiselCircuitAnnotation" in {
33 | val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecFoo)
34 | val res = annotation.elaborate
35 | res(0) shouldBe a [ChiselCircuitAnnotation]
36 | res(1) shouldBe a [DesignAnnotation[ChiselAnnotationsSpecFoo]]
37 | }
38 |
39 | it should "throw an exception if elaboration fails" in {
40 | val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecQux)
41 | intercept [ChiselException] { annotation.elaborate }
42 | }
43 |
44 | behavior of "ChiselGeneratorAnnotation when stringly constructing from Module names"
45 |
46 | it should "elaborate from a String" in {
47 | val annotation = ChiselGeneratorAnnotation("chiselTests.stage.ChiselAnnotationsSpecFoo")
48 | val res = annotation.elaborate
49 | res(0) shouldBe a [ChiselCircuitAnnotation]
50 | res(1) shouldBe a [DesignAnnotation[ChiselAnnotationsSpecFoo]]
51 | }
52 |
53 | it should "throw an exception if elaboration from a String refers to nonexistant class" in {
54 | val bar = "chiselTests.stage.ChiselAnnotationsSpecBar"
55 | val annotation = ChiselGeneratorAnnotation(bar)
56 | intercept [OptionsException] { annotation.elaborate }
57 | .getMessage should startWith (s"Unable to locate module '$bar'")
58 | }
59 |
60 | it should "throw an exception if elaboration from a String refers to an anonymous class" in {
61 | val baz = "chiselTests.stage.ChiselAnnotationsSpecBaz"
62 | val annotation = ChiselGeneratorAnnotation(baz)
63 | intercept [OptionsException] { annotation.elaborate }
64 | .getMessage should startWith (s"Unable to create instance of module '$baz'")
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/util/Lookup.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.util
4 |
5 | import chisel3._
6 |
7 | /** For each element in a list, muxes (looks up) between cases (one per list element) based on a
8 | * common address.
9 | *
10 | * @note This appears to be an odd, specialized operator that we haven't seen used much, and seems
11 | * to be a holdover from chisel2. This may be deprecated and removed, usage is not
12 | * recommended.
13 | *
14 | * @param addr common select for cases, shared (same) across all list elements
15 | * @param default default value for each list element, should the address not match any case
16 | * @param mapping list of cases, where each entry consists of a [[chisel3.util.BitPat BitPath]] (compared against addr) and
17 | * a list of elements (same length as default) that is the output value for that
18 | * element (will have the same index in the output).
19 | *
20 | * @example {{{
21 | * ListLookup(2.U, // address for comparison
22 | * List(10.U, 11.U, 12.U), // default "row" if none of the following cases match
23 | * Array(BitPat(2.U) -> List(20.U, 21.U, 22.U), // this "row" hardware-selected based off address 2.U
24 | * BitPat(3.U) -> List(30.U, 31.U, 32.U))
25 | * ) // hardware-evaluates to List(20.U, 21.U, 22.U)
26 | * // Note: if given address 0.U, the above would hardware evaluate to List(10.U, 11.U, 12.U)
27 | * }}}
28 | */
29 | object ListLookup {
30 | def apply[T <: Data](addr: UInt, default: List[T], mapping: Array[(BitPat, List[T])]): List[T] = {
31 | val map = mapping.map(m => (m._1 === addr, m._2))
32 | default.zipWithIndex map { case (d, i) =>
33 | map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n))
34 | }
35 | }
36 | }
37 |
38 | /** Muxes between cases based on whether an address matches any pattern for a case.
39 | * Similar to [[chisel3.util.MuxLookup MuxLookup]], but uses [[chisel3.util.BitPat BitPat]] for address comparison.
40 | *
41 | * @note This appears to be an odd, specialized operator that we haven't seen used much, and seems
42 | * to be a holdover from chisel2. This may be deprecated and removed, usage is not
43 | * recommended.
44 | *
45 | * @param addr address to select between cases
46 | * @param default default value should the address not match any case
47 | * @param mapping list of cases, where each entry consists of a [[chisel3.util.BitPat BitPat]] (compared against addr) and the
48 | * output value if the BitPat matches
49 | */
50 | object Lookup {
51 | def apply[T <: Bits](addr: UInt, default: T, mapping: Seq[(BitPat, T)]): T =
52 | ListLookup(addr, List(default), mapping.map(m => (m._1, List(m._2))).toArray).head
53 | }
54 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/AnnotationNoDedup.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests
4 |
5 | import chisel3._
6 | import chisel3.experimental.doNotDedup
7 | import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
8 | import firrtl.stage.FirrtlCircuitAnnotation
9 | import org.scalatest.freespec.AnyFreeSpec
10 | import org.scalatest.matchers.should.Matchers
11 |
12 |
13 | class MuchUsedModule extends Module {
14 | val io = IO(new Bundle {
15 | val in = Input(UInt(16.W))
16 | val out = Output(UInt(16.W))
17 | })
18 | io.out := io.in +% 1.U
19 | }
20 |
21 | class UsesMuchUsedModule(addAnnos: Boolean) extends Module {
22 | val io = IO(new Bundle {
23 | val in = Input(UInt(16.W))
24 | val out = Output(UInt(16.W))
25 | })
26 |
27 | val mod0 = Module(new MuchUsedModule)
28 | val mod1 = Module(new MuchUsedModule)
29 | val mod2 = Module(new MuchUsedModule)
30 | val mod3 = Module(new MuchUsedModule)
31 |
32 | mod0.io.in := io.in
33 | mod1.io.in := mod0.io.out
34 | mod2.io.in := mod1.io.out
35 | mod3.io.in := mod2.io.out
36 | io.out := mod3.io.out
37 |
38 | if(addAnnos) {
39 | doNotDedup(mod1)
40 | doNotDedup(mod3)
41 | }
42 | }
43 |
44 | class AnnotationNoDedup extends AnyFreeSpec with Matchers {
45 | val stage = new ChiselStage
46 | "Firrtl provides transform that reduces identical modules to a single instance" - {
47 | "Annotations can be added which will prevent this deduplication for specific modules instances" in {
48 | val lowFirrtl = stage
49 | .execute(Array("-X", "low", "--target-dir", "test_run_dir"),
50 | Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = true))))
51 | .collectFirst {
52 | case FirrtlCircuitAnnotation(circuit) => circuit.serialize
53 | }.getOrElse(fail)
54 | lowFirrtl should include ("module MuchUsedModule :")
55 | lowFirrtl should include ("module MuchUsedModule_1 :")
56 | lowFirrtl should include ("module MuchUsedModule_3 :")
57 | lowFirrtl should not include "module MuchUsedModule_2 :"
58 | lowFirrtl should not include "module MuchUsedModule_4 :"
59 | }
60 | "Turning off these annotations dedups all the occurrences" in {
61 | val lowFirrtl = stage
62 | .execute(Array("-X", "low", "--target-dir", "test_run_dir"),
63 | Seq(ChiselGeneratorAnnotation(() => new UsesMuchUsedModule(addAnnos = false))))
64 | .collectFirst {
65 | case FirrtlCircuitAnnotation(circuit) => circuit.serialize
66 | }.getOrElse(fail)
67 | lowFirrtl should include ("module MuchUsedModule :")
68 | lowFirrtl should not include "module MuchUsedModule_1 :"
69 | lowFirrtl should not include "module MuchUsedModule_3 :"
70 | lowFirrtl should not include "module MuchUsedModule_2 :"
71 | lowFirrtl should not include "module MuchUsedModule_4 :"
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/scala/chisel3/util/experimental/group.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.util.experimental
4 |
5 | import chisel3._
6 | import chisel3.experimental.{ChiselAnnotation, RunFirrtlTransform, annotate}
7 | import chisel3.internal.requireIsHardware
8 | import firrtl.Transform
9 | import firrtl.transforms.{GroupAnnotation, GroupComponents}
10 |
11 | /** Marks that a module to be ignored in Dedup Transform in Firrtl pass
12 | *
13 | * @example {{{
14 | * class MyModule extends Module {
15 | * val io = IO(new Bundle{
16 | * val a = Input(Bool())
17 | * val b = Output(Bool())
18 | * })
19 | * val reg1 = RegInit(0.U)
20 | * reg1 := io.a
21 | * val reg2 = RegNext(reg1)
22 | * io.b := reg2
23 | * group(Seq(reg1, reg2), "DosRegisters", "doubleReg")
24 | * }
25 | * }}}
26 | *
27 | * @note Intermediate wires will get pulled into the new instance, but intermediate registers will not
28 | * because they are also connected to their module's clock port. This means that if you want
29 | * a register to be included in a group, it must be explicitly referred to in the input list.
30 | */
31 | object group {
32 |
33 | /** Marks a set of components (and their interconnected components) to be included in a new
34 | * instance hierarchy.
35 | *
36 | * @note Intermediate wires will get pulled into the new instance, but intermediate registers will not
37 | * because they are also connected to their module's clock port. This means that if you want
38 | * a register to be included in a group, it must be explicitly referred to in the input list.
39 | *
40 | * @param components components in this group
41 | * @param newModule suggested name of the new module
42 | * @param newInstance suggested name of the instance of the new module
43 | * @param outputSuffix suggested suffix of any output ports of the new module
44 | * @param inputSuffix suggested suffix of any input ports of the new module
45 | * @param compileOptions necessary for backwards compatibility
46 | * @tparam T Parent type of input components
47 | */
48 | def apply[T <: Data](
49 | components: Seq[T],
50 | newModule: String,
51 | newInstance: String,
52 | outputSuffix: Option[String] = None,
53 | inputSuffix: Option[String] = None
54 | )(implicit compileOptions: CompileOptions): Unit = {
55 | if (compileOptions.checkSynthesizable) {
56 | components.foreach { data =>
57 | requireIsHardware(data, s"Component ${data.toString} is marked to group, but is not bound.")
58 | }
59 | }
60 | annotate(new ChiselAnnotation with RunFirrtlTransform {
61 | def toFirrtl = GroupAnnotation(components.map(_.toNamed), newModule, newInstance, outputSuffix, inputSuffix)
62 |
63 | override def transformClass: Class[_ <: Transform] = classOf[GroupComponents]
64 | })
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/SETUP.md:
--------------------------------------------------------------------------------
1 | # Chisel Local Setup
2 | Instructions for setting up your environment to run Chisel locally.
3 |
4 | For a minimal setup, you only need to install [SBT (the Scala Build Tool)](http://www.scala-sbt.org), which will automatically fetch the appropriate version of Scala and Chisel based on on your project configuration.
5 |
6 | [Verilator](https://www.veripool.org/wiki/verilator) is optional, only if you need to run the Chisel3 regression suite, or simulate your Verilog designs.
7 | Note that both [PeekPokeTester](https://github.com/freechipsproject/chisel-testers) and [testers2](https://github.com/ucb-bar/chisel-testers2) both support using [treadle](https://github.com/freechipsproject/treadle) (a FIRRTL simulator written in Scala) as the simulation engine, which requires no additional installation steps.
8 |
9 | ## Ubuntu Linux
10 |
11 | 1. Install Java
12 | ```
13 | sudo apt-get install default-jdk
14 | ```
15 |
16 | 1. [Install sbt](http://www.scala-sbt.org/release/docs/Installing-sbt-on-Linux.html),
17 | which isn't available by default in the system package manager:
18 | ```
19 | echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
20 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
21 | sudo apt-get update
22 | sudo apt-get install sbt
23 | ```
24 |
25 | 1. Install Verilator.
26 | We currently recommend Verilator version 4.016.
27 | Follow these instructions to compile it from source.
28 |
29 | 1. Install prerequisites (if not installed already):
30 | ```
31 | sudo apt-get install git make autoconf g++ flex bison
32 | ```
33 |
34 | 2. Clone the Verilator repository:
35 | ```
36 | git clone http://git.veripool.org/git/verilator
37 | ```
38 |
39 | 3. In the Verilator repository directory, check out a known good version:
40 | ```
41 | git pull
42 | git checkout v4.016
43 | ```
44 |
45 | 4. In the Verilator repository directory, build and install:
46 | ```
47 | unset VERILATOR_ROOT # For bash, unsetenv for csh
48 | autoconf # Create ./configure script
49 | ./configure
50 | make
51 | sudo make install
52 | ```
53 |
54 | ## Arch Linux
55 | 1. Install Verilator and SBT
56 | ```
57 | yaourt -S sbt verilator
58 | ```
59 |
60 | ## Windows
61 | 1. [Download and install sbt for Windows](https://www.scala-sbt.org/download.html).
62 |
63 | Verilator does not appear to have native Windows support.
64 | However, Verilator works in [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) or in other Linux-compatible environments like Cygwin.
65 |
66 | There are no issues with generating Verilog from Chisel, which can be pushed to FPGA or ASIC tools.
67 |
68 | ## Mac OS X
69 | 1. Install Verilator and SBT
70 | ```
71 | brew install sbt verilator
72 | ```
73 |
--------------------------------------------------------------------------------
/src/test/scala/chiselTests/util/random/PRNGSpec.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chiselTests.util.random
4 |
5 | import chisel3._
6 | import chisel3.stage.ChiselStage
7 | import chisel3.testers.BasicTester
8 | import chisel3.util.Counter
9 | import chisel3.util.random.PRNG
10 |
11 | import chiselTests.{ChiselFlatSpec, Utils}
12 |
13 | class CyclePRNG(width: Int, seed: Option[BigInt], step: Int, updateSeed: Boolean)
14 | extends PRNG(width, seed, step, updateSeed) {
15 |
16 | def delta(s: Seq[Bool]): Seq[Bool] = s.last +: s.dropRight(1)
17 |
18 | }
19 |
20 | class PRNGStepTest extends BasicTester {
21 |
22 | val count2: UInt = Counter(true.B, 2)._1
23 | val count4: UInt = Counter(true.B, 4)._1
24 |
25 | val a: UInt = PRNG(new CyclePRNG(16, Some(1), 1, false), true.B)
26 | val b: UInt = PRNG(new CyclePRNG(16, Some(1), 2, false), count2 === 1.U)
27 | val c: UInt = PRNG(new CyclePRNG(16, Some(1), 4, false), count4 === 3.U)
28 |
29 | val (_, done) = Counter(true.B, 16)
30 |
31 | when (count2 === 0.U) {
32 | assert(a === b, "1-step and 2-step PRNGs did not agree! (0b%b != 0b%b)", a, b)
33 | }
34 |
35 | when (count4 === 0.U) {
36 | assert(a === c, "1-step and 4-step PRNGs did not agree!")
37 | }
38 |
39 | when (done) {
40 | stop()
41 | }
42 |
43 | }
44 |
45 | class PRNGUpdateSeedTest(updateSeed: Boolean, seed: BigInt, expected: BigInt) extends BasicTester {
46 |
47 | val a: CyclePRNG = Module(new CyclePRNG(16, Some(1), 1, updateSeed))
48 |
49 | val (count, done) = Counter(true.B, 4)
50 |
51 | a.io.increment := true.B
52 | a.io.seed.valid := count === 2.U
53 | a.io.seed.bits := seed.U(a.width.W).asBools
54 |
55 | when (count === 3.U) {
56 | assert(a.io.out.asUInt === expected.U, "Output didn't match!")
57 | }
58 |
59 | when (done) {
60 | stop()
61 | }
62 |
63 | }
64 |
65 | class PRNGSpec extends ChiselFlatSpec with Utils {
66 |
67 | behavior of "PRNG"
68 |
69 | it should "throw an exception if the step size is < 1" in {
70 | { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] {
71 | ChiselStage.elaborate(new CyclePRNG(0, Some(1), 1, true)) }
72 | }.getMessage should include ("Width must be greater than zero!")
73 | }
74 |
75 | it should "throw an exception if the step size is <= 0" in {
76 | { the [IllegalArgumentException] thrownBy extractCause[IllegalArgumentException] {
77 | ChiselStage.elaborate(new CyclePRNG(1, Some(1), 0, true)) }
78 | }.getMessage should include ("Step size must be greater than one!")
79 | }
80 |
81 | it should "handle non-unary steps" in {
82 | assertTesterPasses(new PRNGStepTest)
83 | }
84 |
85 | it should "handle state update without and with updateSeed enabled" in {
86 | info("without updateSeed okay!")
87 | assertTesterPasses(new PRNGUpdateSeedTest(false, 3, 3))
88 |
89 | info("with updateSeed okay!")
90 | assertTesterPasses(new PRNGUpdateSeedTest(true, 3, 6))
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/internal/prefix.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.internal
4 |
5 | /** Use to add a prefix to any components generated in the provided scope.
6 | *
7 | * @example {{{
8 | *
9 | * val x1 = prefix("first") {
10 | * // Anything generated here will be prefixed with "first"
11 | * }
12 | *
13 | * val x2 = prefix(mysignal) {
14 | * // Anything generated here will be prefixed with the name of mysignal
15 | * }
16 | *
17 | * }}}
18 | *
19 | */
20 | private[chisel3] object prefix { // scalastyle:ignore
21 |
22 | /** Use to add a prefix to any components generated in the provided scope
23 | * The prefix is the name of the provided which, which may not be known yet.
24 | *
25 | * @param name The signal/instance whose name will be the prefix
26 | * @param f a function for which any generated components are given the prefix
27 | * @tparam T The return type of the provided function
28 | * @return The return value of the provided function
29 | */
30 | def apply[T](name: HasId)(f: => T): T = {
31 | Builder.pushPrefix(name)
32 | val ret = f
33 | Builder.popPrefix()
34 | ret
35 | }
36 |
37 | /** Use to add a prefix to any components generated in the provided scope
38 | * The prefix is a string, which must be known when this function is used.
39 | *
40 | * @param name The name which will be the prefix
41 | * @param f a function for which any generated components are given the prefix
42 | * @tparam T The return type of the provided function
43 | * @return The return value of the provided function
44 | */
45 | def apply[T](name: String)(f: => T): T = {
46 | Builder.pushPrefix(name)
47 | val ret = f
48 | // Sometimes val's can occur between the Module.apply and Module constructor
49 | // This causes extra prefixes to be added, and subsequently cleared in the
50 | // Module constructor. Thus, we need to just make sure if the previous push
51 | // was an incorrect one, to not pop off an empty stack
52 | if(Builder.getPrefix().nonEmpty) Builder.popPrefix()
53 | ret
54 | }
55 | }
56 |
57 | /** Use to eliminate any existing prefixes within the provided scope.
58 | *
59 | * @example {{{
60 | *
61 | * val x1 = noPrefix {
62 | * // Anything generated here will not be prefixed by anything outside this scope
63 | * }
64 | *
65 | * }}}
66 | *
67 | */
68 | private[chisel3] object noPrefix {
69 |
70 | /** Use to clear existing prefixes so no signals within the scope are prefixed by signals/names
71 | * outside the scope
72 | *
73 | * @param f a function for which any generated components are given the prefix
74 | * @tparam T The return type of the provided function
75 | * @return The return value of the provided function
76 | */
77 | def apply[T](f: => T): T = {
78 | val prefix = Builder.getPrefix()
79 | Builder.clearPrefix()
80 | val ret = f
81 | Builder.setPrefix(prefix)
82 | ret
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/core/src/main/scala/chisel3/Annotation.scala:
--------------------------------------------------------------------------------
1 | // See LICENSE for license details.
2 |
3 | package chisel3.experimental
4 |
5 | import scala.language.existentials
6 | import chisel3.internal.{Builder, InstanceId, LegacyModule}
7 | import chisel3.{CompileOptions, Data}
8 | import firrtl.Transform
9 | import firrtl.annotations._
10 | import firrtl.options.Unserializable
11 | import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation}
12 |
13 | /** Interface for Annotations in Chisel
14 | *
15 | * Defines a conversion to a corresponding FIRRTL Annotation
16 | */
17 | trait ChiselAnnotation {
18 | /** Conversion to FIRRTL Annotation */
19 | def toFirrtl: Annotation
20 | }
21 |
22 | /** Mixin for [[ChiselAnnotation]] that instantiates an associated FIRRTL Transform when this Annotation is present
23 | * during a run of
24 | * [[Driver$.execute(args:Array[String],dut:()=>chisel3\.RawModule)* Driver.execute]].
25 | * Automatic Transform instantiation is *not* supported when the Circuit and Annotations are serialized before invoking
26 | * FIRRTL.
27 | */
28 | trait RunFirrtlTransform extends ChiselAnnotation {
29 | def transformClass: Class[_ <: Transform]
30 | }
31 |
32 | object annotate {
33 | def apply(anno: ChiselAnnotation): Unit = {
34 | Builder.annotations += anno
35 | }
36 | }
37 |
38 | /** Marks that a module to be ignored in Dedup Transform in Firrtl pass
39 | *
40 | * @example {{{
41 | * def fullAdder(a: UInt, b: UInt, myName: String): UInt = {
42 | * val m = Module(new Module {
43 | * val io = IO(new Bundle {
44 | * val a = Input(UInt(32.W))
45 | * val b = Input(UInt(32.W))
46 | * val out = Output(UInt(32.W))
47 | * })
48 | * override def desiredName = "adder_" + myNname
49 | * io.out := io.a + io.b
50 | * })
51 | * doNotDedup(m)
52 | * m.io.a := a
53 | * m.io.b := b
54 | * m.io.out
55 | * }
56 | *
57 | *class AdderTester extends Module
58 | * with ConstantPropagationTest {
59 | * val io = IO(new Bundle {
60 | * val a = Input(UInt(32.W))
61 | * val b = Input(UInt(32.W))
62 | * val out = Output(Vec(2, UInt(32.W)))
63 | * })
64 | *
65 | * io.out(0) := fullAdder(io.a, io.b, "mod1")
66 | * io.out(1) := fullAdder(io.a, io.b, "mod2")
67 | * }
68 | * }}}
69 | *
70 | * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations
71 | * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods
72 | * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically.
73 | */
74 |
75 | object doNotDedup {
76 | /** Marks a module to be ignored in Dedup Transform in Firrtl
77 | *
78 | * @param module The module to be marked
79 | * @return Unmodified signal `module`
80 | */
81 | def apply[T <: LegacyModule](module: T)(implicit compileOptions: CompileOptions): Unit = {
82 | annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) })
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/resources/chisel3/top.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #if VM_TRACE
5 | # include // Trace file format header
6 | #endif
7 |
8 | // Override Verilator definition so first $finish ends simulation
9 | // Note: VL_USER_FINISH needs to be defined when compiling Verilator code
10 | void vl_finish(const char* filename, int linenum, const char* hier) {
11 | Verilated::flushCall();
12 | exit(0);
13 | }
14 |
15 | using namespace std;
16 |
17 | //VGCDTester *top;
18 | TOP_TYPE *top;
19 |
20 | vluint64_t main_time = 0; // Current simulation time
21 | // This is a 64-bit integer to reduce wrap over issues and
22 | // allow modulus. You can also use a double, if you wish.
23 |
24 | double sc_time_stamp () { // Called by $time in Verilog
25 | return main_time; // converts to double, to match
26 | // what SystemC does
27 | }
28 |
29 | // TODO Provide command-line options like vcd filename, timeout count, etc.
30 | const long timeout = 100000000L;
31 |
32 | int main(int argc, char** argv) {
33 | Verilated::commandArgs(argc, argv); // Remember args
34 | top = new TOP_TYPE;
35 |
36 | #if VM_TRACE // If verilator was invoked with --trace
37 | Verilated::traceEverOn(true); // Verilator must compute traced signals
38 | VL_PRINTF("Enabling waves...\n");
39 | VerilatedVcdC* tfp = new VerilatedVcdC;
40 | top->trace (tfp, 99); // Trace 99 levels of hierarchy
41 | tfp->open ("dump.vcd"); // Open the dump file
42 | #endif
43 |
44 |
45 | top->reset = 1;
46 |
47 | cout << "Starting simulation!\n";
48 |
49 | while (!Verilated::gotFinish() && main_time < timeout) {
50 | if (main_time > 10) {
51 | top->reset = 0; // Deassert reset
52 | }
53 | if ((main_time % 10) == 1) {
54 | top->clock = 1; // Toggle clock
55 | }
56 | if ((main_time % 10) == 6) {
57 | top->clock = 0;
58 | }
59 | top->eval(); // Evaluate model
60 | #if VM_TRACE
61 | if (tfp) tfp->dump (main_time); // Create waveform trace for this timestamp
62 | #endif
63 | main_time++; // Time passes...
64 | }
65 |
66 | if (main_time >= timeout) {
67 | cout << "Simulation terminated by timeout at time " << main_time <<
68 | " (cycle " << main_time / 10 << ")"<< endl;
69 | return -1;
70 | } else {
71 | cout << "Simulation completed at time " << main_time <<
72 | " (cycle " << main_time / 10 << ")"<< endl;
73 | }
74 |
75 | // Run for 10 more clocks
76 | vluint64_t end_time = main_time + 100;
77 | while (main_time < end_time) {
78 | if ((main_time % 10) == 1) {
79 | top->clock = 1; // Toggle clock
80 | }
81 | if ((main_time % 10) == 6) {
82 | top->clock = 0;
83 | }
84 | top->eval(); // Evaluate model
85 | #if VM_TRACE
86 | if (tfp) tfp->dump (main_time); // Create waveform trace for this timestamp
87 | #endif
88 | main_time++; // Time passes...
89 | }
90 |
91 | #if VM_TRACE
92 | if (tfp) tfp->close();
93 | #endif
94 | }
95 |
96 |
--------------------------------------------------------------------------------