├── project ├── build.properties └── plugins.sbt ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── src ├── main │ ├── resources │ │ ├── META-INF │ │ │ └── services │ │ │ │ └── firrtl.options.RegisteredLibrary │ │ └── chisel3 │ │ │ ├── Makefile │ │ │ └── top.cpp │ └── scala │ │ └── chisel3 │ │ ├── testers │ │ ├── package.scala │ │ └── BasicTester.scala │ │ ├── stage │ │ ├── ChiselCli.scala │ │ ├── phases │ │ │ ├── MaybeAspectPhase.scala │ │ │ ├── MaybeFirrtlStage.scala │ │ │ ├── Elaborate.scala │ │ │ ├── AddImplicitOutputFile.scala │ │ │ ├── AddImplicitOutputAnnotationFile.scala │ │ │ ├── AspectPhase.scala │ │ │ ├── Convert.scala │ │ │ ├── Checks.scala │ │ │ └── Emitter.scala │ │ ├── ChiselOptions.scala │ │ └── package.scala │ │ ├── util │ │ ├── util.scala │ │ ├── ImplicitConversions.scala │ │ ├── Cat.scala │ │ ├── Enum.scala │ │ ├── CircuitMath.scala │ │ ├── Reg.scala │ │ ├── BlackBoxUtils.scala │ │ ├── OneHot.scala │ │ ├── Lookup.scala │ │ └── experimental │ │ │ └── group.scala │ │ ├── aop │ │ ├── inspecting │ │ │ └── InspectingAspect.scala │ │ ├── injecting │ │ │ ├── InjectStatement.scala │ │ │ └── InjectingTransform.scala │ │ └── AspectLibrary.scala │ │ ├── ChiselExecutionOptions.scala │ │ └── twine │ │ ├── IOInterface.scala │ │ └── hardfloat │ │ └── recFNFromFN.scala ├── test │ ├── scala │ │ ├── chisel3 │ │ │ └── testers │ │ │ │ └── TestUtils.scala │ │ ├── chiselTests │ │ │ ├── RangeSpec.scala │ │ │ ├── EnumSpec.scala │ │ │ ├── DecoupledSpec.scala │ │ │ ├── ModuleExplicitResetSpec.scala │ │ │ ├── WireSpec.scala │ │ │ ├── PopCount.scala │ │ │ ├── Stop.scala │ │ │ ├── IntegerMathSpec.scala │ │ │ ├── RebindingSpec.scala │ │ │ ├── BitwiseOps.scala │ │ │ ├── MulLookup.scala │ │ │ ├── Clock.scala │ │ │ ├── Padding.scala │ │ │ ├── SwitchSpec.scala │ │ │ ├── AdderTree.scala │ │ │ ├── ParameterizedModule.scala │ │ │ ├── Printf.scala │ │ │ ├── stage │ │ │ │ ├── ChiselOptionsViewSpec.scala │ │ │ │ ├── phases │ │ │ │ │ ├── ElaborateSpec.scala │ │ │ │ │ ├── AddImplicitOutputAnnotationFileSpec.scala │ │ │ │ │ ├── AddImplicitOutputFileSpec.scala │ │ │ │ │ ├── ChecksSpec.scala │ │ │ │ │ ├── EmitterSpec.scala │ │ │ │ │ └── ConvertSpec.scala │ │ │ │ ├── ChiselStageSpec.scala │ │ │ │ └── ChiselAnnotationsSpec.scala │ │ │ ├── TesterDriverSpec.scala │ │ │ ├── EnableShiftRegister.scala │ │ │ ├── experimental │ │ │ │ ├── verification │ │ │ │ │ └── VerificationSpec.scala │ │ │ │ └── ProgrammaticPortsSpec.scala │ │ │ ├── InstanceNameSpec.scala │ │ │ ├── ImplicitConversionsSpec.scala │ │ │ ├── Math.scala │ │ │ ├── MissingCloneBindingExceptionSpec.scala │ │ │ ├── GCD.scala │ │ │ ├── IOCompatibility.scala │ │ │ ├── MemorySearch.scala │ │ │ ├── DontTouchSpec.scala │ │ │ ├── Decoder.scala │ │ │ ├── BundleWire.scala │ │ │ ├── MultiIOModule.scala │ │ │ ├── OptionBundle.scala │ │ │ ├── Tbl.scala │ │ │ ├── ComplexAssign.scala │ │ │ ├── TransitNameSpec.scala │ │ │ ├── Stack.scala │ │ │ ├── IllegalRefSpec.scala │ │ │ ├── VectorPacketIO.scala │ │ │ ├── MultiAssign.scala │ │ │ ├── Reg.scala │ │ │ ├── Util.scala │ │ │ ├── Counter.scala │ │ │ ├── Harness.scala │ │ │ ├── ExtModule.scala │ │ │ ├── DedupSpec.scala │ │ │ ├── Assert.scala │ │ │ ├── RawModuleSpec.scala │ │ │ ├── AnnotationNoDedup.scala │ │ │ └── util │ │ │ │ └── random │ │ │ │ └── PRNGSpec.scala │ │ ├── cookbook │ │ │ ├── CookbookSpec.scala │ │ │ ├── VecOfBool2UInt.scala │ │ │ ├── Bundle2UInt.scala │ │ │ ├── UInt2VecOfBool.scala │ │ │ ├── UInt2Bundle.scala │ │ │ ├── RegOfVec.scala │ │ │ └── FSM.scala │ │ └── examples │ │ │ ├── ImplicitStateVendingMachine.scala │ │ │ └── VendingMachineUtils.scala │ └── resources │ │ └── chisel3 │ │ ├── AnalogBlackBox.v │ │ ├── VerilogVendingMachine.v │ │ └── BlackBoxTest.v └── LICENSE.txt ├── doc └── images │ ├── chisel_logo.png │ ├── type_hierarchy.png │ ├── Makefile │ └── type_hierarchy.dot ├── plugin └── src │ └── main │ └── resources │ └── scalac-plugin.xml ├── .scala-steward.conf ├── .scalafix.conf ├── .gitignore ├── core └── src │ └── main │ └── scala │ └── chisel3 │ ├── BoolFactory.scala │ ├── SIntFactory.scala │ ├── ModuleAspect.scala │ ├── aop │ └── Aspect.scala │ ├── experimental │ └── verification │ │ └── package.scala │ ├── dontTouch.scala │ ├── Attach.scala │ ├── Clock.scala │ ├── TwineConnGen.scala │ ├── Mux.scala │ ├── UIntFactory.scala │ ├── MultiClock.scala │ ├── internal │ ├── SourceInfo.scala │ └── prefix.scala │ ├── State.scala │ ├── Element.scala │ ├── Logic.scala │ └── Annotation.scala ├── root-doc.txt ├── macros └── src │ └── main │ └── scala │ └── chisel3 │ ├── SourceInfoDoc.scala │ └── internal │ └── RuntimeDeprecationTransform.scala └── SETUP.md /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.3.10 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @freechipsproject/chisel-reviewers 2 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/firrtl.options.RegisteredLibrary: -------------------------------------------------------------------------------- 1 | chisel3.aop.AspectLibrary 2 | -------------------------------------------------------------------------------- /doc/images/chisel_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Twine-Umich/Twine/HEAD/doc/images/chisel_logo.png -------------------------------------------------------------------------------- /doc/images/type_hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Twine-Umich/Twine/HEAD/doc/images/type_hierarchy.png -------------------------------------------------------------------------------- /plugin/src/main/resources/scalac-plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | chiselplugin 3 | chisel3.plugin.ChiselPlugin 4 | 5 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | updates.ignore = [ { groupId = "edu.berkeley.cs", artifactId = "firrtl" } ] 2 | pullRequests.frequency = "0 0 1 * *" # The first of every month 3 | -------------------------------------------------------------------------------- /.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | # DisableSyntax 3 | # ExplicitResultTypes 4 | #LeakingImplicitClassVal 5 | RemoveUnused 6 | #NoAutoTupling 7 | #NoValInForComprehension 8 | #ProcedureSyntax 9 | ] 10 | 11 | -------------------------------------------------------------------------------- /doc/images/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | 3 | sources = \ 4 | type_hierarchy.dot 5 | 6 | all: $(sources:%.dot=%.svg) $(sources:%.dot=%.png) 7 | 8 | %.svg: %.dot 9 | dot -Tsvg $< -o $@ 10 | 11 | %.png: %.dot 12 | dot -Tpng $< -o $@ 13 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/testers/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | /** The testers package provides the basic interface for chisel testers. 6 | * 7 | */ 8 | package object testers { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | generated/ 3 | /lib/firrtl.jar 4 | .classpath 5 | .idea 6 | .idea_modules/ 7 | .project 8 | target/ 9 | *.iml 10 | *.swp 11 | test_run_dir 12 | *~ 13 | \#*\# 14 | .\#* 15 | .bloop/ 16 | .metals/ 17 | .scalafmt.conf 18 | project/metals.sbt 19 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/ChiselCli.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage 4 | 5 | import firrtl.options.Shell 6 | 7 | trait ChiselCli { this: Shell => 8 | parser.note("Chisel Front End Options") 9 | Seq( NoRunFirrtlCompilerAnnotation, 10 | PrintFullStackTraceAnnotation, 11 | ChiselGeneratorAnnotation ) 12 | .foreach(_.addOptions(parser)) 13 | } 14 | -------------------------------------------------------------------------------- /src/test/scala/chisel3/testers/TestUtils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.testers 4 | 5 | import TesterDriver.Backend 6 | import firrtl.AnnotationSeq 7 | 8 | object TestUtils { 9 | // Useful because TesterDriver.Backend is chisel3 package private 10 | def containsBackend(annos: AnnotationSeq): Boolean = 11 | annos.collectFirst { case b: Backend => b }.isDefined 12 | } 13 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/RangeSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.experimental.ChiselRange 7 | import chisel3.internal.firrtl._ 8 | import firrtl.ir.{Closed, Open} 9 | import org.scalatest.freespec.AnyFreeSpec 10 | import org.scalatest.matchers.should.Matchers 11 | 12 | class RangeSpec extends AnyFreeSpec with Matchers { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/util/util.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | /** The util package provides extensions to core chisel for common hardware components and utility 6 | * functions 7 | */ 8 | package object util { 9 | 10 | /** Synonyms, moved from main package object - maintain scope. */ 11 | type ValidIO[+T <: Data] = chisel3.util.Valid[T] 12 | val ValidIO = chisel3.util.Valid 13 | val DecoupledIO = chisel3.util.Decoupled 14 | } 15 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/EnumSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.util.Enum 7 | import chisel3.testers.BasicTester 8 | 9 | class EnumSpec extends ChiselFlatSpec { 10 | 11 | "1-entry Enums" should "work" in { 12 | assertTesterPasses(new BasicTester { 13 | val onlyState :: Nil = Enum(1) 14 | val wire = WireDefault(onlyState) 15 | chisel3.assert(wire === onlyState) 16 | stop() 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/BoolFactory.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import chisel3.internal.firrtl.{ULit, Width} 6 | 7 | 8 | trait BoolFactory { 9 | /** Creates an empty Bool. 10 | */ 11 | def apply(): Bool = new Bool() 12 | 13 | /** Creates Bool literal. 14 | */ 15 | protected[chisel3] def Lit(x: Boolean): Bool = { 16 | val result = new Bool() 17 | val lit = ULit(if (x) 1 else 0, Width(1)) 18 | // Ensure we have something capable of generating a name. 19 | lit.bindLitArg(result) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/DecoupledSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | import chisel3.util.Decoupled 8 | 9 | class DecoupledSpec extends ChiselFlatSpec { 10 | "Decoupled() and Decoupled.empty" should "give DecoupledIO with empty payloads" in { 11 | ChiselStage.elaborate(new Module { 12 | val io = IO(new Bundle { 13 | val in = Flipped(Decoupled()) 14 | val out = Decoupled.empty 15 | }) 16 | io.out <> io.in 17 | assert(io.asUInt.widthOption.get === 4) 18 | }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/chisel3/AnalogBlackBox.v: -------------------------------------------------------------------------------- 1 | 2 | module AnalogReaderBlackBox( 3 | inout [31:0] bus, 4 | output [31:0] out 5 | ); 6 | assign bus = 32'dz; 7 | assign out = bus; 8 | endmodule 9 | 10 | module AnalogWriterBlackBox( 11 | inout [31:0] bus, 12 | input [31:0] in 13 | ); 14 | assign bus = in; 15 | endmodule 16 | 17 | module AnalogBlackBox #( 18 | parameter index=0 19 | ) ( 20 | inout [31:0] bus, 21 | input port_0_in_valid, 22 | input [31:0] port_0_in_bits, 23 | output [31:0] port_0_out 24 | ); 25 | assign port_0_out = bus; 26 | assign bus = (port_0_in_valid)? port_0_in_bits + index : 32'dZ; 27 | endmodule 28 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/util/ImplicitConversions.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.util 4 | 5 | import chisel3._ 6 | 7 | import scala.language.implicitConversions 8 | 9 | /** Implicit conversions to automatically convert [[scala.Boolean]] and [[scala.Int]] to [[Bool]] 10 | * and [[UInt]] respectively 11 | */ 12 | object ImplicitConversions { 13 | // The explicit fromIntToLiteral resolves an ambiguous conversion between fromIntToLiteral and 14 | // UInt.asUInt. 15 | implicit def intToUInt(x: Int): UInt = chisel3.fromIntToLiteral(x).asUInt 16 | implicit def booleanToBool(x: Boolean): Bool = x.B 17 | } 18 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/ModuleExplicitResetSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3.stage.ChiselStage 6 | 7 | class ModuleExplicitResetSpec extends ChiselFlatSpec { 8 | 9 | "A Module with an explicit reset in compatibility mode" should "elaborate" in { 10 | import Chisel._ 11 | val myReset = true.B 12 | class ModuleExplicitReset(reset: Bool) extends Module(_reset = reset) { 13 | val io = new Bundle { 14 | val done = Bool(OUTPUT) 15 | } 16 | 17 | io.done := false.B 18 | } 19 | 20 | ChiselStage.elaborate { 21 | new ModuleExplicitReset(myReset) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/WireSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | 7 | class WireSpec extends ChiselFlatSpec { 8 | "WireDefault.apply" should "work" in { 9 | assertCompiles("WireDefault(UInt(4.W), 2.U)") 10 | } 11 | it should "allow DontCare" in { 12 | assertCompiles("WireDefault(UInt(4.W), DontCare)") 13 | } 14 | it should "not allow DontCare to affect type inference" in { 15 | assertCompiles("val x: UInt = WireDefault(UInt(4.W), DontCare)") 16 | } 17 | it should "not allow init argument to affect type inference" in { 18 | assertDoesNotCompile("val x: UInt = WireDefault(UInt(4.W), 2.S)") 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/CookbookSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | import chisel3.testers.BasicTester 8 | 9 | import chiselTests.ChiselFlatSpec 10 | 11 | /** Tester for concise cookbook tests 12 | * 13 | * Provides a length of test after which the test will pass 14 | */ 15 | abstract class CookbookTester(length: Int) extends BasicTester { 16 | require(length >= 0, "Simulation length must be non-negative!") 17 | 18 | val (cycle, done) = Counter(true.B, length + 1) // + 1 cycle because done is actually wrap 19 | when (done) { stop() } 20 | } 21 | 22 | abstract class CookbookSpec extends ChiselFlatSpec 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | **Related issue**: 5 | 6 | 7 | **Type of change**: bug report | feature request | documentation | other enhancement 8 | 9 | 10 | **Impact**: no functional change | API addition (no impact on existing code) | API modification 11 | 12 | 13 | **Development Phase**: proposal | implementation 14 | 15 | **Release Notes** 16 | 19 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | resolvers += Resolver.url("scalasbt", new URL("https://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases")) (Resolver.ivyStylePatterns) 2 | 3 | resolvers += Classpaths.sbtPluginReleases 4 | 5 | resolvers += "jgit-repo" at "https://download.eclipse.org/jgit/maven" 6 | 7 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") 8 | 9 | addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.0") 10 | 11 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") 12 | 13 | addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.3") 14 | 15 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.15") 16 | 17 | addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "3.0.0") 18 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/MaybeAspectPhase.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import chisel3.aop.Aspect 6 | import firrtl.AnnotationSeq 7 | import firrtl.options.{Dependency, Phase, PreservesAll} 8 | 9 | /** Run [[AspectPhase]] if a [[chisel3.aop.Aspect]] is present. 10 | */ 11 | class MaybeAspectPhase extends Phase with PreservesAll[Phase] { 12 | 13 | override val prerequisites = Seq(Dependency[Elaborate]) 14 | 15 | def transform(annotations: AnnotationSeq): AnnotationSeq = { 16 | if(annotations.collectFirst { case a: Aspect[_] => annotations }.isDefined) { 17 | new AspectPhase().transform(annotations) 18 | } else annotations 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/VecOfBool2UInt.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | 7 | /* ### How do I create a UInt from a Vec of Bool? 8 | * 9 | * Use the builtin function asUInt 10 | */ 11 | class VecOfBool2UInt extends CookbookTester(1) { 12 | // Example 13 | val vec = VecInit(true.B, false.B, true.B, true.B) 14 | val uint = vec.asUInt 15 | printf(p"$uint") // 13 16 | 17 | /* Test 18 | * 19 | * (remember leftmost Bool in Vec is low order bit) 20 | */ 21 | assert(0xd.U === uint) 22 | } 23 | 24 | class VecOfBool2UIntSpec extends CookbookSpec { 25 | "VecOfBool2UInt" should "work" in { 26 | assertTesterPasses { new VecOfBool2UInt } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/PopCount.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.util.PopCount 7 | import chisel3.testers.BasicTester 8 | 9 | class PopCountTester(n: Int) extends BasicTester { 10 | val x = RegInit(0.U(n.W)) 11 | x := x + 1.U 12 | when (RegNext(x === ~0.U(n.W))) { stop() } 13 | 14 | val result = PopCount(x.asBools) 15 | val expected = x.asBools.foldLeft(0.U)(_ +& _) 16 | assert(result === expected) 17 | 18 | require(result.getWidth == BigInt(n).bitLength) 19 | } 20 | 21 | class PopCountSpec extends ChiselPropSpec { 22 | property("Mul lookup table should return the correct result") { 23 | forAll(smallPosInts) { (n: Int) => assertTesterPasses { new PopCountTester(n) } } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/Bundle2UInt.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | 7 | /* ### How do I create a UInt from an instance of a Bundle? 8 | * 9 | * Call asUInt on the Bundle instance 10 | */ 11 | class Bundle2UInt extends CookbookTester(1) { 12 | // Example 13 | class MyBundle extends Bundle { 14 | val foo = UInt(4.W) 15 | val bar = UInt(4.W) 16 | } 17 | val bundle = Wire(new MyBundle) 18 | bundle.foo := 0xc.U 19 | bundle.bar := 0x3.U 20 | val uint = bundle.asUInt 21 | printf(p"$uint") // 195 22 | 23 | // Test 24 | assert(uint === 0xc3.U) 25 | } 26 | 27 | class Bundle2UIntSpec extends CookbookSpec { 28 | "Bundle2UInt" should "work" in { 29 | assertTesterPasses { new Bundle2UInt } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Stop.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class StopTester() extends BasicTester { 9 | stop() 10 | } 11 | 12 | class StopImmediatelyTester extends BasicTester { 13 | val cycle = RegInit(0.asUInt(4.W)) 14 | cycle := cycle + 1.U 15 | when (cycle === 4.U) { 16 | stop() 17 | } 18 | assert(cycle =/= 5.U, "Simulation did not exit upon executing stop()") 19 | } 20 | 21 | class StopSpec extends ChiselFlatSpec { 22 | "stop()" should "stop and succeed the testbench" in { 23 | assertTesterPasses { new StopTester } 24 | } 25 | 26 | it should "end the simulation immediately" in { 27 | assertTesterPasses { new StopImmediatelyTester } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/IntegerMathSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class IntegerMathTester extends BasicTester { 9 | 10 | //TODO: Add more operators 11 | 12 | /* absolute values tests */ 13 | 14 | val uint = 3.U(4.W) 15 | val sint = (-3).S 16 | val sintpos = 3.S 17 | val wrongSIntPos = 4.S 18 | 19 | assert(uint.abs() === uint) 20 | assert(sint.abs() === sintpos) 21 | assert(sintpos.abs() === sintpos) 22 | 23 | assert(sint.abs() =/= wrongSIntPos) 24 | 25 | stop() 26 | } 27 | 28 | class IntegerMathSpec extends ChiselPropSpec { 29 | property("All integer ops should return the correct result") { 30 | assertTesterPasses{ new IntegerMathTester } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/SIntFactory.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import chisel3.internal.firrtl.{IntervalRange, SLit, Width} 6 | 7 | trait SIntFactory { 8 | /** Create an SInt type with inferred width. */ 9 | def apply(): SInt = apply(Width()) 10 | /** Create a SInt type or port with fixed width. */ 11 | def apply(width: Width): SInt = new SInt(width) 12 | 13 | /** Create a SInt with the specified range */ 14 | def apply(range: IntervalRange): SInt = { 15 | apply(range.getWidth) 16 | } 17 | 18 | /** Create an SInt literal with specified width. */ 19 | protected[chisel3] def Lit(value: BigInt, width: Width): SInt = { 20 | val lit = SLit(value, width) 21 | val result = new SInt(lit.width) 22 | lit.bindLitArg(result) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/MaybeFirrtlStage.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import chisel3.stage.NoRunFirrtlCompilerAnnotation 6 | 7 | import firrtl.AnnotationSeq 8 | import firrtl.options.{Dependency, Phase, PreservesAll} 9 | import firrtl.stage.FirrtlStage 10 | 11 | /** Run [[firrtl.stage.FirrtlStage]] if a [[chisel3.stage.NoRunFirrtlCompilerAnnotation]] is not present. 12 | */ 13 | class MaybeFirrtlStage extends Phase with PreservesAll[Phase] { 14 | 15 | override val prerequisites = Seq(Dependency[Convert]) 16 | 17 | def transform(annotations: AnnotationSeq): AnnotationSeq = annotations 18 | .collectFirst { case NoRunFirrtlCompilerAnnotation => annotations } 19 | .getOrElse { (new FirrtlStage).transform(annotations) } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/UInt2VecOfBool.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | 7 | /* ### How do I create a Vec of Bools from a UInt? 8 | * 9 | * Use the builtin function [[chisel3.Bits.asBools]] to create a Scala Seq of Bool, 10 | * then wrap the resulting Seq in Vec(...) 11 | */ 12 | class UInt2VecOfBool extends CookbookTester(1) { 13 | // Example 14 | val uint = 0xc.U 15 | val vec = VecInit(uint.asBools) 16 | printf(p"$vec") // Vec(0, 0, 1, 1) 17 | 18 | // Test 19 | assert(vec(0) === false.B) 20 | assert(vec(1) === false.B) 21 | assert(vec(2) === true.B) 22 | assert(vec(3) === true.B) 23 | } 24 | 25 | class UInt2VecOfBoolSpec extends CookbookSpec { 26 | "UInt2VecOfBool" should "work" in { 27 | assertTesterPasses { new UInt2VecOfBool } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/RebindingSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | 8 | class RebindingSpec extends ChiselFlatSpec with Utils { 9 | "Rebinding a literal" should "fail" in { 10 | a [BindingException] should be thrownBy extractCause[BindingException] { 11 | ChiselStage.elaborate { new Module { 12 | val io = IO(new Bundle { 13 | val a = 4.U 14 | }) 15 | } } 16 | } 17 | } 18 | 19 | "Rebinding a hardware type" should "fail" in { 20 | a [BindingException] should be thrownBy extractCause[BindingException] { 21 | ChiselStage.elaborate { new Module { 22 | val io = IO(new Bundle { 23 | val a = Reg(UInt(32.W)) 24 | }) 25 | } } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/UInt2Bundle.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | 7 | /* ### How do I create a Bundle from a UInt? 8 | * 9 | * On an instance of the Bundle, call the method fromBits with the UInt as the argument 10 | */ 11 | class UInt2Bundle extends CookbookTester(1) { 12 | // Example 13 | class MyBundle extends Bundle { 14 | val foo = UInt(4.W) 15 | val bar = UInt(4.W) 16 | } 17 | val uint = 0xb4.U 18 | val bundle = uint.asTypeOf(new MyBundle) 19 | printf(p"$bundle") // Bundle(foo -> 11, bar -> 4) 20 | 21 | // Test 22 | assert(bundle.foo === 0xb.U) 23 | assert(bundle.bar === 0x4.U) 24 | } 25 | 26 | class UInt2BundleSpec extends CookbookSpec { 27 | "UInt2Bundle" should "work" in { 28 | assertTesterPasses { new UInt2Bundle } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /root-doc.txt: -------------------------------------------------------------------------------- 1 | This is the documentation for Chisel. 2 | 3 | == Package structure == 4 | 5 | The [[chisel3]] package presents the public API of Chisel. 6 | It contains the concrete core types [[chisel3.UInt `UInt`]], [[chisel3.SInt `SInt`]], [[chisel3.Bool `Bool`]], [[chisel3.experimental.FixedPoint `FixedPoint`]], [[chisel3.Clock `Clock`]], and [[chisel3.Reg `Reg`]], 7 | the abstract types [[chisel3.Bits `Bits`]], [[chisel3.Aggregate `Aggregate`]], and [[chisel3.Data `Data`]], 8 | and the aggregate types [[chisel3.Bundle `Bundle`]] and [[chisel3.Vec `Vec`]]. 9 | 10 | The [[Chisel]] package is a compatibility layer that attempts to provide chisel2 compatibility in chisel3. 11 | 12 | Utility objects and methods are found in the [[chisel3.util `util`]] package. 13 | 14 | The [[chisel3.testers `testers`]] package defines the basic interface for chisel testers. 15 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/Elaborate.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import java.io.{PrintWriter, StringWriter} 6 | 7 | import chisel3.ChiselException 8 | import chisel3.internal.ErrorLog 9 | import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOptions} 10 | import firrtl.AnnotationSeq 11 | import firrtl.options.Viewer.view 12 | import firrtl.options.{OptionsException, Phase, PreservesAll} 13 | 14 | /** Elaborate all [[chisel3.stage.ChiselGeneratorAnnotation]]s into [[chisel3.stage.ChiselCircuitAnnotation]]s. 15 | */ 16 | class Elaborate extends Phase with PreservesAll[Phase] { 17 | 18 | def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap { 19 | case a: ChiselGeneratorAnnotation => a.elaborate 20 | case a => Some(a) 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/chisel3/Makefile: -------------------------------------------------------------------------------- 1 | # Chisel parallel make template. 2 | 3 | HFILES = @HFILES@ 4 | ONCEONLY = @ONCEONLY@ 5 | UNOPTIMIZED = @UNOPTIMIZED@ 6 | OPTIMIZED = @OPTIMIZED@ 7 | 8 | EXEC = @EXEC@ 9 | OPTIM0 = @OPTIM0@ 10 | OPTIM1 = @OPTIM1@ 11 | OPTIM2 = @OPTIM2@ 12 | CPPFLAGS = @CPPFLAGS@ 13 | CXXFLAGS = @CXXFLAGS@ 14 | LDFLAGS = @LDFLAGS@ 15 | CXX = @CXX@ 16 | 17 | default: $(EXEC) 18 | 19 | clean: 20 | $(RM) $(EXEC) $(ONCEONLY) $(UNOPTIMIZED) $(OPTIMIZED) 21 | 22 | $(ONCEONLY) $(UNOPTIMIZED) $(OPTIMIZED): $(HFILES) 23 | 24 | $(EXEC): $(ONCEONLY) $(UNOPTIMIZED) $(OPTIMIZED) Makefile 25 | $(CXX) -o $@ $(filter-out Makefile,$^) 26 | 27 | $(ONCEONLY): %.o: %.cpp 28 | $(CXX) -c -o $@ $(OPTIM0) $(CPPFLAGS) $(CXXFLAGS) $< 29 | 30 | $(UNOPTIMIZED): %.o: %.cpp 31 | $(CXX) -c -o $@ $(OPTIM1) $(CPPFLAGS) $(CXXFLAGS) $< 32 | 33 | $(OPTIMIZED): %.o: %.cpp 34 | $(CXX) -c -o $@ $(OPTIM2) $(CPPFLAGS) $(CXXFLAGS) $< 35 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/BitwiseOps.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class BitwiseOpsTester(w: Int, _a: Int, _b: Int) extends BasicTester { 9 | val mask = (1 << w) - 1 10 | val a = _a.asUInt(w.W) 11 | val b = _b.asUInt(w.W) 12 | assert(~a === (mask & ~_a).asUInt) 13 | assert((a & b) === (_a & _b).asUInt) 14 | assert((a | b) === (_a | _b).asUInt) 15 | assert((a ^ b) === (_a ^ _b).asUInt) 16 | assert((a.orR) === (_a != 0).asBool) 17 | assert((a.andR) === (s"%${w}s".format(BigInt(_a).toString(2)).foldLeft(true)(_ && _ == '1') ).asBool) 18 | stop() 19 | } 20 | 21 | class BitwiseOpsSpec extends ChiselPropSpec { 22 | property("All bit-wise ops should return the correct result") { 23 | forAll(safeUIntPair) { case(w: Int, a: Int, b: Int) => 24 | assertTesterPasses{ new BitwiseOpsTester(w, a, b) } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/aop/inspecting/InspectingAspect.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.aop.inspecting 4 | 5 | import chisel3.RawModule 6 | import chisel3.aop.Aspect 7 | import firrtl.AnnotationSeq 8 | 9 | /** Use for inspecting an elaborated design and printing out results 10 | * 11 | * @param inspect Given top-level design, print things and return nothing 12 | * @tparam T Type of top-level module 13 | */ 14 | case class InspectingAspect[T <: RawModule](inspect: T => Unit) extends InspectorAspect[T](inspect) 15 | 16 | 17 | /** Extend to make custom inspections of an elaborated design and printing out results 18 | * 19 | * @param inspect Given top-level design, print things and return nothing 20 | * @tparam T Type of top-level module 21 | */ 22 | abstract class InspectorAspect[T <: RawModule](inspect: T => Unit) extends Aspect[T] { 23 | override def toAnnotation(top: T): AnnotationSeq = { 24 | inspect(top) 25 | Nil 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/ChiselOptions.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage 4 | 5 | import chisel3.internal.firrtl.Circuit 6 | 7 | class ChiselOptions private[stage] ( 8 | val runFirrtlCompiler: Boolean = true, 9 | val printFullStackTrace: Boolean = false, 10 | val outputFile: Option[String] = None, 11 | val chiselCircuit: Option[Circuit] = None) { 12 | 13 | private[stage] def copy( 14 | runFirrtlCompiler: Boolean = runFirrtlCompiler, 15 | printFullStackTrace: Boolean = printFullStackTrace, 16 | outputFile: Option[String] = outputFile, 17 | chiselCircuit: Option[Circuit] = chiselCircuit ): ChiselOptions = { 18 | 19 | new ChiselOptions( 20 | runFirrtlCompiler = runFirrtlCompiler, 21 | printFullStackTrace = printFullStackTrace, 22 | outputFile = outputFile, 23 | chiselCircuit = chiselCircuit ) 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/ModuleAspect.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import chisel3.internal.Builder 6 | 7 | /** Used by Chisel Aspects to inject Chisel code into modules, after they have been elaborated. 8 | * This is an internal API - don't use! 9 | * 10 | * It adds itself as an aspect to the module, which allows proper checking of connection and binding legality. 11 | * 12 | * @param module Module for which this object is an aspect of 13 | * @param moduleCompileOptions 14 | */ 15 | abstract class ModuleAspect private[chisel3] (module: RawModule) 16 | (implicit moduleCompileOptions: CompileOptions) extends RawModule { 17 | 18 | Builder.addAspect(module, this) 19 | 20 | val in = IO(new Bundle() {}) 21 | val out = IO(new Bundle() {}) 22 | override def circuitName: String = module.toTarget.circuit 23 | 24 | override def desiredName: String = module.name 25 | 26 | override val _namespace = module._namespace 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/AddImplicitOutputFile.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import firrtl.AnnotationSeq 6 | import firrtl.options.{Dependency, Phase, PreservesAll} 7 | 8 | import chisel3.stage.{ChiselCircuitAnnotation, ChiselOutputFileAnnotation} 9 | 10 | /** Add a output file for a Chisel circuit, derived from the top module in the circuit, if no 11 | * [[ChiselOutputFileAnnotation]] already exists. 12 | */ 13 | class AddImplicitOutputFile extends Phase with PreservesAll[Phase] { 14 | 15 | override val prerequisites = Seq(Dependency[Elaborate]) 16 | 17 | def transform(annotations: AnnotationSeq): AnnotationSeq = 18 | annotations.collectFirst{ case _: ChiselOutputFileAnnotation => annotations }.getOrElse{ 19 | 20 | val x: Option[AnnotationSeq] = annotations 21 | .collectFirst{ case a: ChiselCircuitAnnotation => 22 | ChiselOutputFileAnnotation(a.circuit.name) +: annotations } 23 | 24 | x.getOrElse(annotations) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/scala/examples/ImplicitStateVendingMachine.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package examples 4 | 5 | import chiselTests.ChiselFlatSpec 6 | import chisel3._ 7 | 8 | // Vending machine implemented with an implicit state machine 9 | class ImplicitStateVendingMachine extends SimpleVendingMachine { 10 | // We let the value of nickel be 1 and dime be 2 for efficiency reasons 11 | val value = RegInit(0.asUInt(3.W)) 12 | val incValue = WireDefault(0.asUInt(3.W)) 13 | val doDispense = value >= 4.U // 4 * nickel as 1 == $0.20 14 | 15 | when (doDispense) { 16 | value := 0.U // No change given 17 | } .otherwise { 18 | value := value + incValue 19 | } 20 | 21 | when (io.nickel) { incValue := 1.U } 22 | when (io.dime) { incValue := 2.U } 23 | 24 | io.dispense := doDispense 25 | } 26 | 27 | class ImplicitStateVendingMachineSpec extends ChiselFlatSpec { 28 | "An vending machine implemented with implicit state" should "work" in { 29 | assertTesterPasses { new SimpleVendingMachineTester(new ImplicitStateVendingMachine) } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/aop/injecting/InjectStatement.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.aop.injecting 4 | 5 | import chisel3.stage.phases.AspectPhase 6 | import firrtl.annotations.{Annotation, ModuleTarget, NoTargetAnnotation, SingleTargetAnnotation} 7 | 8 | /** Contains all information needed to inject statements into a module 9 | * 10 | * Generated when a [[InjectingAspect]] is consumed by a [[AspectPhase]] 11 | * Consumed by [[InjectingTransform]] 12 | * 13 | * @param module Module to inject code into at the end of the module 14 | * @param s Statements to inject 15 | * @param modules Additional modules that may be instantiated by s 16 | * @param annotations Additional annotations that should be passed down compiler 17 | */ 18 | case class InjectStatement(module: ModuleTarget, s: firrtl.ir.Statement, modules: Seq[firrtl.ir.DefModule], annotations: Seq[Annotation]) extends SingleTargetAnnotation[ModuleTarget] { 19 | val target: ModuleTarget = module 20 | override def duplicate(n: ModuleTarget): Annotation = this.copy(module = n) 21 | } 22 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/MulLookup.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class MulLookup(val w: Int) extends Module { 9 | val io = IO(new Bundle { 10 | val x = Input(UInt(w.W)) 11 | val y = Input(UInt(w.W)) 12 | val z = Output(UInt((2 * w).W)) 13 | }) 14 | val tbl = VecInit( 15 | for { 16 | i <- 0 until 1 << w 17 | j <- 0 until 1 << w 18 | } yield (i * j).asUInt((2 * w).W) 19 | ) 20 | io.z := tbl(((io.x << w) | io.y)) 21 | } 22 | 23 | class MulLookupTester(w: Int, x: Int, y: Int) extends BasicTester { 24 | val dut = Module(new MulLookup(w)) 25 | dut.io.x := x.asUInt 26 | dut.io.y := y.asUInt 27 | assert(dut.io.z === (x * y).asUInt) 28 | stop() 29 | } 30 | 31 | class MulLookupSpec extends ChiselPropSpec { 32 | 33 | property("Mul lookup table should return the correct result") { 34 | forAll(smallPosInts, smallPosInts) { (x: Int, y: Int) => 35 | assertTesterPasses{ new MulLookupTester(3, x, y) } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Clock.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 ClockAsUIntTester extends BasicTester { 10 | assert(true.B.asClock.asUInt === 1.U) 11 | assert(true.B.asClock.asBool === true.B) 12 | stop() 13 | } 14 | 15 | class WithClockAndNoReset extends RawModule { 16 | val clock1 = IO(Input(Clock())) 17 | val clock2 = IO(Input(Clock())) 18 | val in = IO(Input(Bool())) 19 | val out = IO(Output(Bool())) 20 | val a = withClock(clock2) { 21 | RegNext(in) 22 | } 23 | 24 | out := a 25 | } 26 | 27 | 28 | class ClockSpec extends ChiselPropSpec { 29 | property("Bool.asClock.asUInt should pass a signal through unaltered") { 30 | assertTesterPasses { new ClockAsUIntTester } 31 | } 32 | 33 | property("Should be able to use withClock in a module with no reset") { 34 | val circuit = (new ChiselStage).emitChirrtl(new WithClockAndNoReset) 35 | circuit.contains("reg a : UInt<1>, clock2") should be (true) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/AddImplicitOutputAnnotationFile.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import chisel3.stage.ChiselCircuitAnnotation 6 | import firrtl.AnnotationSeq 7 | import firrtl.options.{Dependency, OutputAnnotationFileAnnotation, Phase, PreservesAll} 8 | 9 | /** Adds an [[firrtl.options.OutputAnnotationFileAnnotation]] if one does not exist. This replicates old behavior where 10 | * an output annotation file was always written. 11 | */ 12 | class AddImplicitOutputAnnotationFile extends Phase with PreservesAll[Phase] { 13 | 14 | override val prerequisites = Seq(Dependency[Elaborate]) 15 | 16 | def transform(annotations: AnnotationSeq): AnnotationSeq = annotations 17 | .collectFirst{ case _: OutputAnnotationFileAnnotation => annotations } 18 | .getOrElse{ 19 | 20 | val x: Option[AnnotationSeq] = annotations 21 | .collectFirst{ case a: ChiselCircuitAnnotation => 22 | OutputAnnotationFileAnnotation(a.circuit.name) +: annotations } 23 | 24 | x.getOrElse(annotations) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Padding.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | 8 | class Padder extends Module { 9 | val io = IO(new Bundle { 10 | val a = Input(UInt(4.W)) 11 | val asp = Output(SInt(8.W)) 12 | val aup = Output(UInt(8.W)) 13 | }) 14 | io.asp := io.a.asSInt 15 | io.aup := io.a.asUInt 16 | } 17 | 18 | /* 19 | class PadsTester(c: Pads) extends Tester(c) { 20 | def pads(x: BigInt, s: Int, w: Int) = { 21 | val sign = (x & (1 << (s-1))) 22 | val wmask = (1 << w) - 1 23 | val bmask = (1 << s) - 1 24 | if (sign == 0) x else ((~bmask | x) & wmask) 25 | } 26 | for (t <- 0 until 16) { 27 | val test_a = rnd.nextInt(1 << 4) 28 | poke(c.io.a, test_a) 29 | step(1) 30 | expect(c.io.asp, pads(test_a, 4, 8)) 31 | expect(c.io.aup, test_a) 32 | } 33 | } 34 | */ 35 | 36 | class PadderSpec extends ChiselPropSpec { 37 | 38 | property("Padder should elaborate") { 39 | ChiselStage.elaborate { new Padder } 40 | } 41 | 42 | ignore("PadderTester should return the correct result") { } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/util/Cat.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.util 4 | 5 | import chisel3._ 6 | 7 | /** Concatenates elements of the input, in order, together. 8 | * 9 | * @example {{{ 10 | * Cat("b101".U, "b11".U) // equivalent to "b101 11".U 11 | * Cat(myUIntWire0, myUIntWire1) 12 | * 13 | * Cat(Seq("b101".U, "b11".U)) // equivalent to "b101 11".U 14 | * Cat(mySeqOfBits) 15 | * }}} 16 | */ 17 | object Cat { 18 | /** Concatenates the argument data elements, in argument order, together. The first argument 19 | * forms the most significant bits, while the last argument forms the least significant bits. 20 | */ 21 | def apply[T <: Bits](a: T, r: T*): UInt = apply(a :: r.toList) 22 | 23 | /** Concatenates the data elements of the input sequence, in reverse sequence order, together. 24 | * The first element of the sequence forms the most significant bits, while the last element 25 | * in the sequence forms the least significant bits. 26 | * 27 | * Equivalent to r(0) ## r(1) ## ... ## r(n-1). 28 | */ 29 | def apply[T <: Bits](r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse) 30 | } 31 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/SwitchSpec.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 SwitchSpec extends ChiselFlatSpec with Utils { 10 | "switch" should "require literal conditions" in { 11 | a [java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { 12 | ChiselStage.elaborate(new Module { 13 | val io = IO(new Bundle {}) 14 | val state = RegInit(0.U) 15 | val wire = WireDefault(0.U) 16 | switch (state) { 17 | is (wire) { state := 1.U } 18 | } 19 | }) 20 | } 21 | } 22 | it should "require mutually exclusive conditions" in { 23 | a [java.lang.IllegalArgumentException] should be thrownBy extractCause[IllegalArgumentException] { 24 | ChiselStage.elaborate(new Module { 25 | val io = IO(new Bundle {}) 26 | val state = RegInit(0.U) 27 | switch (state) { 28 | is (0.U) { state := 1.U } 29 | is (1.U) { state := 2.U } 30 | is (0.U) { state := 3.U } 31 | } 32 | }) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/AdderTree.scala: -------------------------------------------------------------------------------- 1 | package chiselTests 2 | 3 | import chisel3._ 4 | import chisel3.testers.BasicTester 5 | 6 | class AdderTree[T <: Bits with Num[T]](genType: T, vecSize: Int) extends Module { 7 | val io = IO(new Bundle { 8 | val numIn = Input(Vec(vecSize, genType)) 9 | val numOut = Output(genType) 10 | }) 11 | io.numOut := io.numIn.reduceTree((a : T, b : T) => (a + b)) 12 | } 13 | 14 | class AdderTreeTester(bitWidth: Int, numsToAdd: List[Int]) extends BasicTester { 15 | val genType = UInt(bitWidth.W) 16 | val dut = Module(new AdderTree(genType, numsToAdd.size)) 17 | dut.io.numIn := VecInit(numsToAdd.map(x => x.asUInt(bitWidth.W))) 18 | val sumCorrect = dut.io.numOut === (numsToAdd.reduce(_+_) % (1 << bitWidth)).asUInt(bitWidth.W) 19 | assert(sumCorrect) 20 | stop() 21 | } 22 | 23 | class AdderTreeSpec extends ChiselPropSpec { 24 | property("All numbers should be added correctly by an Adder Tree") { 25 | forAll(safeUIntN(20)) { 26 | case (w: Int, v: List[Int]) => { 27 | whenever(v.size > 0 && w > 0) { 28 | assertTesterPasses { new AdderTreeTester(w, v.map(x => math.abs(x) % ( 1 << w )).toList) } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/AspectPhase.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import chisel3.aop.Aspect 6 | import chisel3.RawModule 7 | import chisel3.stage.DesignAnnotation 8 | import firrtl.AnnotationSeq 9 | import firrtl.options.Phase 10 | 11 | import scala.collection.mutable 12 | 13 | /** Phase that consumes all Aspects and calls their toAnnotationSeq methods. 14 | * 15 | * Consumes the [[chisel3.stage.DesignAnnotation]] and converts every [[Aspect]] into their annotations prior to executing FIRRTL 16 | */ 17 | class AspectPhase extends Phase { 18 | def transform(annotations: AnnotationSeq): AnnotationSeq = { 19 | var dut: Option[RawModule] = None 20 | val aspects = mutable.ArrayBuffer[Aspect[_]]() 21 | 22 | val remainingAnnotations = annotations.flatMap { 23 | case DesignAnnotation(d) => 24 | dut = Some(d) 25 | Nil 26 | case a: Aspect[_] => 27 | aspects += a 28 | Nil 29 | case other => Seq(other) 30 | } 31 | if(dut.isDefined) { 32 | val newAnnotations = aspects.flatMap { _.resolveAspect(dut.get) } 33 | remainingAnnotations ++ newAnnotations 34 | } else annotations 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/RegOfVec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | 7 | /* ### How do I create a Reg of type Vec? 8 | * 9 | * For information, please see the API documentation for Vec 10 | * (https://chisel.eecs.berkeley.edu/api/index.html#chisel3.Vec) 11 | */ 12 | class RegOfVec extends CookbookTester(2) { 13 | // Reg of Vec of 32-bit UInts without initialization 14 | val regOfVec = Reg(Vec(4, UInt(32.W))) 15 | regOfVec(0) := 123.U // a couple of assignments 16 | regOfVec(2) := regOfVec(0) 17 | 18 | // Reg of Vec of 32-bit UInts initialized to zero 19 | // Note that Seq.fill constructs 4 32-bit UInt literals with the value 0 20 | // Vec(...) then constructs a Wire of these literals 21 | // The Reg is then initialized to the value of the Wire (which gives it the same type) 22 | val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W)))) 23 | 24 | // Simple test (cycle comes from superclass) 25 | when (cycle === 2.U) { assert(regOfVec(2) === 123.U) } 26 | for (elt <- initRegOfVec) { assert(elt === 0.U) } 27 | } 28 | 29 | class RegOfVecSpec extends CookbookSpec { 30 | "RegOfVec" should "work" in { 31 | assertTesterPasses { new RegOfVec } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/util/Enum.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | /** Enum generators, allowing circuit constants to have more meaningful names. 4 | */ 5 | 6 | package chisel3.util 7 | 8 | import chisel3._ 9 | import chisel3.internal.chiselRuntimeDeprecated 10 | 11 | /** Defines a set of unique UInt constants 12 | * 13 | * Unpack with a list to specify an enumeration. Usually used with [[switch]] to describe a finite 14 | * state machine. 15 | * 16 | * @example {{{ 17 | * val state_on :: state_off :: Nil = Enum(2) 18 | * val current_state = WireDefault(state_off) 19 | * switch (current_state) { 20 | * is (state_on) { 21 | * ... 22 | * } 23 | * is (state_off) { 24 | * ... 25 | * } 26 | * } 27 | * }}} 28 | */ 29 | trait Enum { 30 | /** Returns a sequence of Bits subtypes with values from 0 until n. Helper method. */ 31 | protected def createValues(n: Int): Seq[UInt] = 32 | (0 until n).map(_.U((1 max log2Ceil(n)).W)) 33 | 34 | /** Returns n unique UInt values 35 | * 36 | * @param n Number of unique UInt constants to enumerate 37 | * @return Enumerated constants 38 | */ 39 | def apply(n: Int): List[UInt] = createValues(n).toList 40 | } 41 | 42 | object Enum extends Enum 43 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/ParameterizedModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class ParameterizedModule(invert: Boolean) extends Module { 9 | val io = IO(new Bundle { 10 | val in = Input(Bool()) 11 | val out = Output(Bool()) 12 | }) 13 | if (invert) { 14 | io.out := !io.in 15 | } else { 16 | io.out := io.in 17 | } 18 | } 19 | 20 | /** A simple test to check Module deduplication doesn't affect correctness (two 21 | * modules with the same name but different contents aren't aliased). Doesn't 22 | * check that deduplication actually happens, though. 23 | */ 24 | class ParameterizedModuleTester() extends BasicTester { 25 | val invert = Module(new ParameterizedModule(true)) 26 | val noninvert = Module(new ParameterizedModule(false)) 27 | 28 | invert.io.in := true.B 29 | noninvert.io.in := true.B 30 | assert(invert.io.out === false.B) 31 | assert(noninvert.io.out === true.B) 32 | 33 | stop() 34 | } 35 | 36 | class ParameterizedModuleSpec extends ChiselFlatSpec { 37 | "Different parameterized modules" should "have different behavior" in { 38 | assertTesterPasses(new ParameterizedModuleTester()) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Printf.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class SinglePrintfTester() extends BasicTester { 9 | val x = 254.U 10 | printf("x=%x", x) 11 | stop() 12 | } 13 | 14 | class ASCIIPrintfTester() extends BasicTester { 15 | printf((0x20 to 0x7e).map(_.toChar).mkString.replace("%", "%%")) 16 | stop() 17 | } 18 | 19 | class MultiPrintfTester() extends BasicTester { 20 | val x = 254.U 21 | val y = 255.U 22 | printf("x=%x y=%x", x, y) 23 | stop() 24 | } 25 | 26 | class ASCIIPrintableTester extends BasicTester { 27 | printf(PString((0x20 to 0x7e) map (_.toChar) mkString "")) 28 | stop() 29 | } 30 | 31 | class PrintfSpec extends ChiselFlatSpec { 32 | "A printf with a single argument" should "run" in { 33 | assertTesterPasses { new SinglePrintfTester } 34 | } 35 | "A printf with multiple arguments" should "run" in { 36 | assertTesterPasses { new MultiPrintfTester } 37 | } 38 | "A printf with ASCII characters 1-127" should "run" in { 39 | assertTesterPasses { new ASCIIPrintfTester } 40 | } 41 | "A printf with Printable ASCII characters 1-127" should "run" in { 42 | assertTesterPasses { new ASCIIPrintableTester } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/resources/chisel3/VerilogVendingMachine.v: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | // A simple Verilog FSM vending machine implementation 4 | module VerilogVendingMachine( 5 | input clock, 6 | input reset, 7 | input nickel, 8 | input dime, 9 | output dispense 10 | ); 11 | parameter sIdle = 3'd0, s5 = 3'd1, s10 = 3'd2, s15 = 3'd3, sOk = 3'd4; 12 | reg [2:0] state; 13 | 14 | assign dispense = (state == sOk) ? 1'd1 : 1'd0; 15 | 16 | always @(posedge clock) begin 17 | if (reset) begin 18 | state <= sIdle; 19 | end else begin 20 | case (state) 21 | sIdle: begin 22 | if (nickel) state <= s5; 23 | else if (dime) state <= s10; 24 | else state <= state; 25 | end 26 | s5: begin 27 | if (nickel) state <= s10; 28 | else if (dime) state <= s15; 29 | else state <= state; 30 | end 31 | s10: begin 32 | if (nickel) state <= s15; 33 | else if (dime) state <= sOk; 34 | else state <= state; 35 | end 36 | s15: begin 37 | if (nickel) state <= sOk; 38 | else if (dime) state <= sOk; 39 | else state <= state; 40 | end 41 | sOk: begin 42 | state <= sIdle; 43 | end 44 | endcase 45 | end 46 | end 47 | endmodule 48 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests.stage 4 | 5 | 6 | import firrtl.options.Viewer.view 7 | 8 | import chisel3.stage._ 9 | import chisel3.internal.firrtl.Circuit 10 | import org.scalatest.flatspec.AnyFlatSpec 11 | import org.scalatest.matchers.should.Matchers 12 | 13 | class ChiselOptionsViewSpec extends AnyFlatSpec with Matchers { 14 | 15 | behavior of ChiselOptionsView.getClass.getName 16 | 17 | it should "construct a view from an AnnotationSeq" in { 18 | val bar = Circuit("bar", Seq.empty, Seq.empty) 19 | val annotations = Seq( 20 | NoRunFirrtlCompilerAnnotation, 21 | PrintFullStackTraceAnnotation, 22 | ChiselOutputFileAnnotation("foo"), 23 | ChiselCircuitAnnotation(bar) 24 | ) 25 | val out = view[ChiselOptions](annotations) 26 | 27 | info("runFirrtlCompiler was set to false") 28 | out.runFirrtlCompiler should be (false) 29 | 30 | info("printFullStackTrace was set to true") 31 | out.printFullStackTrace should be (true) 32 | 33 | info("outputFile was set to 'foo'") 34 | out.outputFile should be (Some("foo")) 35 | 36 | info("chiselCircuit was set to circuit 'bar'") 37 | out.chiselCircuit should be (Some(bar)) 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /doc/images/type_hierarchy.dot: -------------------------------------------------------------------------------- 1 | digraph TypeHierarchy { 2 | graph [rankdir=BT bgcolor="transparent"] 3 | { node [style=filled,shape=box] 4 | { node [fillcolor="#f7fbff"] 5 | Data 6 | Element 7 | Bits Num 8 | Aggregate 9 | VecLike 10 | "Chisel Internal" 11 | } 12 | { node [fillcolor="#e5f5e0"] 13 | Bool UInt SInt FixedPoint 14 | Reset 15 | AsyncReset 16 | Record 17 | Bundle 18 | Vec 19 | "Chisel Types" 20 | } 21 | { node [fillcolor="#fcbba1"] 22 | "User Types" 23 | Ellipsis [label="..."] 24 | } 25 | 26 | subgraph cluster_data_hierarchy { 27 | color=transparent 28 | Element 29 | Bits Num 30 | Reset 31 | Bool UInt SInt FixedPoint 32 | color=transparent 33 | Aggregate 34 | VecLike 35 | Record 36 | Bundle 37 | Vec 38 | 39 | {Aggregate Element} -> Data 40 | {Bits Reset} -> Element 41 | {FixedPoint SInt UInt} -> {Bits Num} 42 | Bool -> {UInt Reset} 43 | Ellipsis -> Bundle -> Record -> Aggregate 44 | Vec -> {Aggregate VecLike} 45 | AsyncReset -> {Element Reset} 46 | } 47 | subgraph cluster_legend { 48 | label=Legend 49 | "User Types" -> "Chisel Types" -> "Chisel Internal" 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/scala/examples/VendingMachineUtils.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package examples 4 | 5 | import scala.collection.mutable 6 | 7 | /* Useful utilities for testing vending machines */ 8 | object VendingMachineUtils { 9 | abstract class Coin(val name: String, val value: Int) 10 | // US Coins 11 | case object Penny extends Coin("penny", 1) 12 | case object Nickel extends Coin("nickel", 5) 13 | case object Dime extends Coin("dime", 10) 14 | case object Quarter extends Coin("quarter", 25) 15 | 16 | // Harry Potter Coins 17 | case object Knut extends Coin("knut", Penny.value * 2) // Assuming 1 Knut is worth $0.02 18 | case object Sickle extends Coin("sickle", Knut.value * 29) 19 | case object Galleon extends Coin("galleon", Sickle.value * 17) 20 | 21 | def getExpectedResults(inputs: Seq[Option[Coin]], sodaCost: Int): Seq[Boolean] = { 22 | var value = 0 23 | val outputs = mutable.ArrayBuffer.empty[Boolean] 24 | for (input <- inputs) { 25 | val incValue = input match { 26 | case Some(coin) => coin.value 27 | case None => 0 28 | } 29 | if (value >= sodaCost) { 30 | outputs.append(true) 31 | value = 0 32 | } else { 33 | outputs.append(false) 34 | value += incValue 35 | } 36 | } 37 | outputs 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | **Type of issue**: bug report | feature request | documentation | other enhancement 8 | 9 | 10 | **Impact**: no functional change | API addition (no impact on existing code) | API modification | unknown 11 | 12 | 13 | **Development Phase**: request | proposal 14 | 15 | **Other information** 16 | 17 | 18 | **If the current behavior is a bug, please provide the steps to reproduce the problem:** 19 | 20 | **What is the current behavior?** 21 | 22 | **What is the expected behavior?** 23 | 24 | **Please tell us about your environment:** 25 | 29 | **What is the use case for changing the behavior?** 30 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/util/CircuitMath.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | /** Circuit-land math operations. 4 | */ 5 | 6 | package chisel3.util 7 | 8 | import chisel3._ 9 | import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order 10 | 11 | /** Returns the base-2 integer logarithm of an UInt. 12 | * 13 | * @note The result is truncated, so e.g. Log2(13.U) === 3.U 14 | * 15 | * @example {{{ 16 | * Log2(8.U) // evaluates to 3.U 17 | * Log2(13.U) // evaluates to 3.U (truncation) 18 | * Log2(myUIntWire) 19 | * }}} 20 | * 21 | */ 22 | object Log2 { 23 | /** Returns the base-2 integer logarithm of the least-significant `width` bits of an UInt. 24 | */ 25 | @chiselName 26 | def apply(x: Bits, width: Int): UInt = { 27 | if (width < 2) { 28 | 0.U 29 | } else if (width == 2) { 30 | x(1) 31 | } else if (width <= divideAndConquerThreshold) { 32 | Mux(x(width-1), (width-1).asUInt, apply(x, width-1)) 33 | } else { 34 | val mid = 1 << (log2Ceil(width) - 1) 35 | val hi = x(width-1, mid) 36 | val lo = x(mid-1, 0) 37 | val useHi = hi.orR 38 | Cat(useHi, Mux(useHi, Log2(hi, width - mid), Log2(lo, mid))) 39 | } 40 | } 41 | 42 | def apply(x: Bits): UInt = apply(x, x.getWidth) 43 | 44 | private def divideAndConquerThreshold = 4 45 | } 46 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/aop/Aspect.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.aop 4 | 5 | import chisel3.RawModule 6 | import firrtl.annotations.{Annotation, NoTargetAnnotation} 7 | import firrtl.options.Unserializable 8 | import firrtl.AnnotationSeq 9 | 10 | /** Represents an aspect of a Chisel module, by specifying 11 | * what behavior should be done to instance, via the FIRRTL Annotation Mechanism 12 | * @tparam T Type of top-level module 13 | */ 14 | abstract class Aspect[T <: RawModule] extends Annotation with Unserializable with NoTargetAnnotation { 15 | /** Convert this Aspect to a seq of FIRRTL annotation 16 | * @param top 17 | * @return 18 | */ 19 | def toAnnotation(top: T): AnnotationSeq 20 | 21 | /** Called by [[chisel3.stage.phases.AspectPhase]] to resolve this Aspect into annotations 22 | * @param top 23 | * @return 24 | */ 25 | private[chisel3] def resolveAspect(top: RawModule): AnnotationSeq = { 26 | toAnnotation(top.asInstanceOf[T]) 27 | } 28 | } 29 | 30 | /** Holds utility functions for Aspect stuff */ 31 | object Aspect { 32 | 33 | /** Converts elaborated Chisel components to FIRRTL modules 34 | * @param chiselIR 35 | * @return 36 | */ 37 | def getFirrtl(chiselIR: chisel3.internal.firrtl.Circuit): firrtl.ir.Circuit = { 38 | chisel3.internal.firrtl.Converter.convert(chiselIR) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/experimental/verification/package.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.experimental 4 | 5 | import chisel3.{Bool, CompileOptions} 6 | import chisel3.internal.Builder 7 | import chisel3.internal.Builder.pushCommand 8 | import chisel3.internal.firrtl.{Formal, Verification} 9 | import chisel3.internal.sourceinfo.SourceInfo 10 | 11 | package object verification { 12 | object assert { 13 | def apply(predicate: Bool, msg: String = "")( 14 | implicit sourceInfo: SourceInfo, 15 | compileOptions: CompileOptions): Unit = { 16 | val clock = Builder.forcedClock 17 | pushCommand(Verification(Formal.Assert, sourceInfo, clock.ref, 18 | predicate.ref, msg)) 19 | } 20 | } 21 | 22 | object assume { 23 | def apply(predicate: Bool, msg: String = "")( 24 | implicit sourceInfo: SourceInfo, 25 | compileOptions: CompileOptions): Unit = { 26 | val clock = Builder.forcedClock 27 | pushCommand(Verification(Formal.Assume, sourceInfo, clock.ref, 28 | predicate.ref, msg)) 29 | } 30 | } 31 | 32 | object cover { 33 | def apply(predicate: Bool, msg: String = "")( 34 | implicit sourceInfo: SourceInfo, 35 | compileOptions: CompileOptions): Unit = { 36 | val clock = Builder.forcedClock 37 | pushCommand(Verification(Formal.Cover, sourceInfo, clock.ref, 38 | predicate.ref, msg)) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/TesterDriverSpec.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 | /** Extend BasicTester with a simple circuit and finish method. TesterDriver will call the 10 | * finish method after the FinishTester's constructor has completed, which will alter the 11 | * circuit after the constructor has finished. 12 | */ 13 | class FinishTester extends BasicTester { 14 | val test_wire_width = 2 15 | val test_wire_override_value = 3 16 | 17 | val counter = Counter(1) 18 | 19 | when(counter.inc()) { 20 | stop() 21 | } 22 | 23 | val test_wire = WireDefault(1.U(test_wire_width.W)) 24 | 25 | // though we just set test_wire to 1, the assert below will pass because 26 | // the finish will change its value 27 | assert(test_wire === test_wire_override_value.asUInt) 28 | 29 | /** In finish we use last connect semantics to alter the test_wire in the circuit 30 | * with a new value 31 | */ 32 | override def finish(): Unit = { 33 | test_wire := test_wire_override_value.asUInt 34 | } 35 | } 36 | 37 | class TesterDriverSpec extends ChiselFlatSpec { 38 | "TesterDriver calls BasicTester's finish method which" should 39 | "allow modifications of test circuit after the tester's constructor is done" in { 40 | assertTesterPasses { 41 | new FinishTester 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/EnableShiftRegister.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | import chisel3._ 5 | import chisel3.stage.ChiselStage 6 | 7 | class EnableShiftRegister extends Module { 8 | val io = IO(new Bundle { 9 | val in = Input(UInt(4.W)) 10 | val shift = Input(Bool()) 11 | val out = Output(UInt(4.W)) 12 | }) 13 | val r0 = RegInit(0.U(4.W)) 14 | val r1 = RegInit(0.U(4.W)) 15 | val r2 = RegInit(0.U(4.W)) 16 | val r3 = RegInit(0.U(4.W)) 17 | when(io.shift) { 18 | r0 := io.in 19 | r1 := r0 20 | r2 := r1 21 | r3 := r2 22 | } 23 | io.out := r3 24 | } 25 | 26 | /* 27 | class EnableShiftRegisterTester(c: EnableShiftRegister) extends Tester(c) { 28 | val reg = Array.fill(4){ 0 } 29 | for (t <- 0 until 16) { 30 | val in = rnd.nextInt(16) 31 | val shift = rnd.nextInt(2) 32 | println("SHIFT " + shift + " IN " + in) 33 | poke(c.io.in, in) 34 | poke(c.io.shift, shift) 35 | step(1) 36 | if (shift == 1) { 37 | for (i <- 3 to 1 by -1) 38 | reg(i) = reg(i-1) 39 | reg(0) = in 40 | } 41 | expect(c.io.out, reg(3)) 42 | } 43 | } 44 | */ 45 | 46 | class EnableShiftRegisterSpec extends ChiselPropSpec { 47 | 48 | property("EnableShiftRegister should elaborate") { 49 | ChiselStage.elaborate { new EnableShiftRegister } 50 | } 51 | 52 | ignore("EnableShiftRegisterTester should return the correct result") { } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests.experimental.verification 4 | 5 | import chisel3._ 6 | import chisel3.experimental.{verification => formal} 7 | import chisel3.stage.ChiselStage 8 | import chiselTests.ChiselPropSpec 9 | 10 | class VerificationModule extends Module { 11 | val io = IO(new Bundle{ 12 | val in = Input(UInt(8.W)) 13 | val out = Output(UInt(8.W)) 14 | }) 15 | io.out := io.in 16 | formal.cover(io.in === 3.U) 17 | when (io.in === 3.U) { 18 | formal.assume(io.in =/= 2.U) 19 | formal.assert(io.out === io.in) 20 | } 21 | } 22 | 23 | class VerificationSpec extends ChiselPropSpec { 24 | 25 | def assertContains[T](s: Seq[T], x: T): Unit = { 26 | val containsLine = s.map(_ == x).reduce(_ || _) 27 | assert(containsLine, s"\n $x\nwas not found in`\n ${s.mkString("\n ")}``") 28 | } 29 | 30 | property("basic equality check should work") { 31 | val stage = new ChiselStage 32 | val fir = stage.emitFirrtl(new VerificationModule) 33 | val lines = fir.split("\n").map(_.trim) 34 | assertContains(lines, "cover(clock, _T, UInt<1>(\"h1\"), \"\") @[VerificationSpec.scala 16:15]") 35 | assertContains(lines, "assume(clock, _T_2, UInt<1>(\"h1\"), \"\") @[VerificationSpec.scala 18:18]") 36 | assertContains(lines, "assert(clock, _T_3, UInt<1>(\"h1\"), \"\") @[VerificationSpec.scala 19:18]") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/InstanceNameSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | import chisel3.util.Queue 8 | 9 | class InstanceNameModule extends Module { 10 | val io = IO(new Bundle { 11 | val foo = Input(UInt(32.W)) 12 | val bar = Output(UInt(32.W)) 13 | }) 14 | val x = 3.U 15 | val y = UInt(8.W) 16 | val z = new Bundle { 17 | val foo = UInt(8.W) 18 | } 19 | 20 | val q = Module(new Queue(UInt(32.W), 4)) 21 | 22 | io.bar := io.foo + x 23 | } 24 | 25 | class InstanceNameSpec extends ChiselFlatSpec { 26 | behavior of "instanceName" 27 | val moduleName = "InstanceNameModule" 28 | var m: InstanceNameModule = _ 29 | ChiselStage.elaborate { m = new InstanceNameModule; m } 30 | 31 | it should "work with module IO" in { 32 | val io = m.io.pathName 33 | assert(io == moduleName + ".io") 34 | } 35 | 36 | it should "work with internal vals" in { 37 | val x = m.x.pathName 38 | val y = m.y.pathName 39 | val z = m.z.pathName 40 | assert(x == moduleName + ".UInt<2>(\"h03\")") 41 | assert(y == moduleName + ".y") 42 | assert(z == moduleName + ".z") 43 | } 44 | 45 | it should "work with bundle elements" in { 46 | val foo = m.z.foo.pathName 47 | assert(foo == moduleName + ".z.foo") 48 | } 49 | 50 | it should "work with modules" in { 51 | val q = m.q.pathName 52 | assert(q == moduleName + ".q") 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/dontTouch.scala: -------------------------------------------------------------------------------- 1 | package chisel3 2 | 3 | import chisel3.experimental.{ChiselAnnotation, annotate, requireIsHardware} 4 | import firrtl.transforms.DontTouchAnnotation 5 | 6 | /** Marks that a signal should not be removed by Chisel and Firrtl optimization passes 7 | * 8 | * @example {{{ 9 | * class MyModule extends Module { 10 | * val io = IO(new Bundle { 11 | * val a = Input(UInt(32.W)) 12 | * val b = Output(UInt(32.W)) 13 | * }) 14 | * io.b := io.a 15 | * val dead = io.a +% 1.U // normally dead would be pruned by DCE 16 | * dontTouch(dead) // Marking it as such will preserve it 17 | * } 18 | * }}} 19 | * @note Calling this on [[Data]] creates an annotation that Chisel emits to a separate annotations 20 | * file. This file must be passed to FIRRTL independently of the `.fir` file. The execute methods 21 | * in [[chisel3.Driver]] will pass the annotations to FIRRTL automatically. 22 | */ 23 | object dontTouch { 24 | /** Marks a signal to be preserved in Chisel and Firrtl 25 | * 26 | * @note Requires the argument to be bound to hardware 27 | * @param data The signal to be marked 28 | * @return Unmodified signal `data` 29 | */ 30 | def apply[T <: Data](data: T)(implicit compileOptions: CompileOptions): T = { 31 | if (compileOptions.checkSynthesizable) { 32 | requireIsHardware(data, "Data marked dontTouch") 33 | } 34 | annotate(new ChiselAnnotation { def toFirrtl = DontTouchAnnotation(data.toNamed) }) 35 | data 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/testers/BasicTester.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.testers 4 | import chisel3._ 5 | 6 | import scala.language.experimental.macros 7 | 8 | import chisel3.internal.Builder.pushCommand 9 | import chisel3.internal.firrtl._ 10 | import chisel3.internal.sourceinfo.SourceInfo 11 | 12 | class BasicTester extends Module() { 13 | // The testbench has no IOs, rather it should communicate using printf, assert, and stop. 14 | val io = IO(new Bundle() {}) 15 | 16 | val in = IO(new Bundle() {}) 17 | val out = IO(new Bundle() {}) 18 | 19 | def popCount(n: Long): Int = n.toBinaryString.count(_=='1') 20 | 21 | /** Ends the test reporting success. 22 | * 23 | * Does not fire when in reset (defined as the encapsulating Module's 24 | * reset). If your definition of reset is not the encapsulating Module's 25 | * reset, you will need to gate this externally. 26 | */ 27 | def stop()(implicit sourceInfo: SourceInfo) { 28 | // TODO: rewrite this using library-style SourceInfo passing. 29 | when (!reset.asBool) { 30 | pushCommand(Stop(sourceInfo, clock.ref, 0)) 31 | } 32 | } 33 | 34 | /** The finish method provides a hook that subclasses of BasicTester can use to 35 | * alter a circuit after their constructor has been called. 36 | * For example, a specialized tester subclassing BasicTester could override finish in order to 37 | * add flow control logic for a decoupled io port of a device under test 38 | */ 39 | def finish(): Unit = {} 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/Attach.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.experimental 4 | 5 | import chisel3.RawModule 6 | import chisel3.internal._ 7 | import chisel3.internal.Builder.pushCommand 8 | import chisel3.internal.firrtl._ 9 | import chisel3.internal.sourceinfo.SourceInfo 10 | 11 | object attach { 12 | // Exceptions that can be generated by attach 13 | case class AttachException(message: String) extends ChiselException(message) 14 | def ConditionalAttachException: AttachException = 15 | AttachException(": Conditional attach is not allowed!") 16 | 17 | // Actual implementation 18 | private[chisel3] def impl(elts: Seq[Analog], contextModule: RawModule)(implicit sourceInfo: SourceInfo): Unit = { 19 | if (Builder.whenDepth != 0) throw ConditionalAttachException 20 | 21 | // TODO Check that references are valid and can be attached 22 | 23 | pushCommand(Attach(sourceInfo, elts.map(_.lref))) 24 | } 25 | 26 | /** Create an electrical connection between [[Analog]] components 27 | * 28 | * @param elts The components to attach 29 | * 30 | * @example 31 | * {{{ 32 | * val a1 = Wire(Analog(32.W)) 33 | * val a2 = Wire(Analog(32.W)) 34 | * attach(a1, a2) 35 | * }}} 36 | */ 37 | def apply(elts: Analog*)(implicit sourceInfo: SourceInfo): Unit = { 38 | try { 39 | impl(elts, Builder.forcedUserModule) 40 | } catch { 41 | case AttachException(message) => 42 | throwException(elts.mkString("Attaching (", ", ", s") failed @$message")) 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/test/resources/chisel3/BlackBoxTest.v: -------------------------------------------------------------------------------- 1 | module BlackBoxInverter( 2 | input [0:0] in, 3 | output [0:0] out 4 | ); 5 | assign out = !in; 6 | endmodule 7 | 8 | module BlackBoxPassthrough( 9 | input [0:0] in, 10 | output [0:0] out 11 | ); 12 | assign out = in; 13 | endmodule 14 | 15 | module BlackBoxPassthrough2( 16 | input [0:0] in, 17 | output [0:0] out 18 | ); 19 | assign out = in; 20 | endmodule 21 | 22 | module BlackBoxMinus( 23 | input [15:0] in1, 24 | input [15:0] in2, 25 | output [15:0] out 26 | ); 27 | assign out = in1 + in2; 28 | endmodule 29 | 30 | module BlackBoxRegister( 31 | input [0:0] clock, 32 | input [0:0] in, 33 | output [0:0] out 34 | ); 35 | reg [0:0] register; 36 | always @(posedge clock) begin 37 | register <= in; 38 | end 39 | assign out = register; 40 | endmodule 41 | 42 | module BlackBoxConstant #( 43 | parameter int WIDTH=1, 44 | parameter int VALUE=1 45 | ) ( 46 | output [WIDTH-1:0] out 47 | ); 48 | assign out = VALUE; 49 | endmodule 50 | 51 | module BlackBoxStringParam #( 52 | parameter string STRING = "zero" 53 | ) ( 54 | output [31:0] out 55 | ); 56 | assign out = (STRING == "one" )? 1 : 57 | (STRING == "two" )? 2 : 0; 58 | endmodule 59 | 60 | module BlackBoxRealParam #( 61 | parameter real REAL = 0.0 62 | ) ( 63 | output [63:0] out 64 | ); 65 | assign out = $realtobits(REAL); 66 | endmodule 67 | 68 | module BlackBoxTypeParam #( 69 | parameter type T = bit 70 | ) ( 71 | output T out 72 | ); 73 | assign out = 32'hdeadbeef; 74 | endmodule 75 | -------------------------------------------------------------------------------- /src/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Chisel3 license terms 2 | 3 | Copyright (c) 2014 - 2019 The Regents of the University of 4 | California (Regents). All Rights Reserved. Redistribution and use in 5 | source and binary forms, with or without modification, are permitted 6 | provided that the following conditions are met: 7 | * Redistributions of source code must retain the above 8 | copyright notice, this list of conditions and the following 9 | two paragraphs of disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | two paragraphs of disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | * Neither the name of the Regents nor the names of its contributors 15 | may be used to endorse or promote products derived from this 16 | software without specific prior written permission. 17 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 18 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, 19 | ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 20 | REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF 24 | ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION 25 | TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 26 | MODIFICATIONS. 27 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests.stage.phases 4 | 5 | 6 | import chisel3._ 7 | import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation} 8 | import chisel3.stage.phases.Elaborate 9 | 10 | import firrtl.options.Phase 11 | import org.scalatest.flatspec.AnyFlatSpec 12 | import org.scalatest.matchers.should.Matchers 13 | 14 | class ElaborateSpec extends AnyFlatSpec with Matchers { 15 | 16 | class Foo extends Module { 17 | override def desiredName: String = "Foo" 18 | val io = IO( 19 | new Bundle { 20 | val in = Input(Bool()) 21 | val out = Output(Bool()) 22 | }) 23 | 24 | io.out := ~io.in 25 | } 26 | 27 | class Bar extends Foo { 28 | override def desiredName: String = "Bar" 29 | } 30 | 31 | class Fixture { val phase: Phase = new Elaborate } 32 | 33 | behavior of classOf[Elaborate].toString 34 | 35 | it should "expand ChiselGeneratorAnnotations into ChiselCircuitAnnotations and delete originals" in new Fixture { 36 | val annotations = Seq( ChiselGeneratorAnnotation(() => new Foo), 37 | ChiselGeneratorAnnotation(() => new Bar) ) 38 | val out = phase.transform(annotations) 39 | 40 | info("original annotations removed") 41 | out.collect{ case a: ChiselGeneratorAnnotation => a } should be (empty) 42 | 43 | info("circuits created with the expected names") 44 | out.collect{ case a: ChiselCircuitAnnotation => a.circuit.name } should be (Seq("Foo", "Bar")) 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/ImplicitConversionsSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | 7 | class ImplicitConversionsSpec extends ChiselFlatSpec { 8 | ".data on arbitrary Data objects" should "not work" in { 9 | assertTypeError("UInt(8.W).data") 10 | assertTypeError("8.S.data") 11 | assertTypeError("(new Bundle {}).data") 12 | assertTypeError("VecInit(1.U).data") 13 | } 14 | 15 | ".target on arbitrary Data objects" should "not work" in { 16 | assertTypeError("UInt(8.W).target") 17 | assertTypeError("8.S.target") 18 | assertTypeError("(new Bundle {}).target") 19 | assertTypeError("VecInit(1.U).target") 20 | } 21 | 22 | ".x on Strings and Numerical values" should "not work" in { 23 | assertTypeError("3.x") 24 | assertTypeError("3L.x") 25 | assertTypeError("BigInt(-4).x") 26 | assertTypeError("false.x") 27 | assertTypeError(""""a".x""") 28 | } 29 | 30 | ".bigint on Strings and Numerical values" should "not work" in { 31 | assertTypeError("3.bigint") 32 | assertTypeError("3L.bigint") 33 | assertTypeError("BigInt(-4).bigint") 34 | assertTypeError("false.bigint") 35 | assertTypeError(""""a".bigint""") 36 | } 37 | 38 | ".target on DecoupledIO" should "not work" in { 39 | import chisel3.util._ 40 | assertTypeError("Decoupled(UInt(8.W)).target") 41 | } 42 | 43 | "X.B for X not in [0,1]" should "throw an exception, even outside hardware context" in { 44 | a [ChiselException] should be thrownBy { 45 | 65.B 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Math.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import org.scalacheck.Shrink 6 | 7 | class Math extends ChiselPropSpec { 8 | import chisel3.util._ 9 | // Disable shrinking on error. 10 | implicit val noShrinkListVal = Shrink[List[Int]](_ => Stream.empty) 11 | implicit val noShrinkInt = Shrink[Int](_ => Stream.empty) 12 | 13 | property ("unsignedBitLength is computed correctly") { 14 | forAll(safeUIntWidth) { case (width: Int) => 15 | for ( offset <- List(-1, 0, 1)) { 16 | val n = (1 << width) + offset 17 | if (n >= 0) { 18 | val d = unsignedBitLength(n) 19 | val t = if (n == 0) 0 else if (offset < 0) width else width + 1 20 | d shouldEqual (t) 21 | } 22 | } 23 | } 24 | } 25 | 26 | property ("signedBitLength is computed correctly") { 27 | forAll(safeUIntWidth) { case (width: Int) => 28 | for ( offset <- List(-1, 0, 1)) { 29 | for ( mult <- List(-1, +1)) { 30 | val n = ((1 << (width - 1)) + offset) * mult 31 | val d = signedBitLength(n) 32 | val t = n match { 33 | case -2 => 2 34 | case -1 => 1 35 | case 0 => 0 36 | case 1 => 2 37 | case 2 => 3 38 | case _ => 39 | if (n > 0) { 40 | if (offset < 0) width else width + 1 41 | } else { 42 | if (offset > 0) width + 1 else width 43 | } 44 | } 45 | d shouldEqual (t) 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/MissingCloneBindingExceptionSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | import Chisel.ChiselException 5 | import chisel3.stage.ChiselStage 6 | import org.scalatest._ 7 | import org.scalatest.matchers.should.Matchers 8 | 9 | class MissingCloneBindingExceptionSpec extends ChiselFlatSpec with Matchers with Utils { 10 | behavior of "missing cloneType in Chisel3" 11 | ( the [ChiselException] thrownBy extractCause[ChiselException] { 12 | import chisel3._ 13 | 14 | class Test extends Module { 15 | class TestIO(w: Int) extends Bundle { 16 | val a = Input(Vec(4, UInt(w.W))) 17 | } 18 | 19 | val io = IO(new TestIO(32)) 20 | } 21 | 22 | class TestTop extends Module { 23 | val io = IO(new Bundle {}) 24 | 25 | val subs = VecInit(Seq.fill(2) { 26 | Module(new Test).io 27 | }) 28 | } 29 | 30 | ChiselStage.elaborate(new TestTop) 31 | }).getMessage should include("make all parameters immutable") 32 | 33 | behavior of "missing cloneType in Chisel2" 34 | ( the [ChiselException] thrownBy extractCause[ChiselException] { 35 | import Chisel._ 36 | 37 | class Test extends Module { 38 | class TestIO(w: Int) extends Bundle { 39 | val a = Vec(4, UInt(width = w)).asInput 40 | } 41 | 42 | val io = IO(new TestIO(32)) 43 | } 44 | 45 | class TestTop extends Module { 46 | val io = IO(new Bundle {}) 47 | 48 | val subs = Vec.fill(2) { 49 | Module(new Test).io 50 | } 51 | } 52 | 53 | ChiselStage.elaborate(new TestTop) 54 | }).getMessage should include("make all parameters immutable") 55 | } 56 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/GCD.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 GCD extends Module { 10 | val io = IO(new Bundle { 11 | val a = Input(UInt(32.W)) 12 | val b = Input(UInt(32.W)) 13 | val e = Input(Bool()) 14 | val z = Output(UInt(32.W)) 15 | val v = Output(Bool()) 16 | }) 17 | val x = Reg(UInt(32.W)) 18 | val y = Reg(UInt(32.W)) 19 | when (x > y) { x := x -% y } 20 | .otherwise { y := y -% x } 21 | when (io.e) { x := io.a; y := io.b } 22 | io.z := x 23 | io.v := y === 0.U 24 | } 25 | 26 | class GCDTester(a: Int, b: Int, z: Int) extends BasicTester { 27 | val dut = Module(new GCD) 28 | val first = RegInit(true.B) 29 | dut.io.a := a.U 30 | dut.io.b := b.U 31 | dut.io.e := first 32 | when(first) { first := false.B } 33 | when(!first && dut.io.v) { 34 | assert(dut.io.z === z.U) 35 | stop() 36 | } 37 | } 38 | 39 | class GCDSpec extends ChiselPropSpec { 40 | 41 | //TODO: use generators and this function to make z's 42 | def gcd(a: Int, b: Int): Int = if(b == 0) a else gcd(b, a%b) 43 | 44 | val gcds = Table( 45 | ("a", "b", "z"), // First tuple defines column names 46 | ( 64, 48, 16), // Subsequent tuples define the data 47 | ( 12, 9, 3), 48 | ( 48, 64, 16)) 49 | 50 | property("GCD should elaborate") { 51 | ChiselStage.elaborate { new GCD } 52 | } 53 | 54 | property("GCDTester should return the correct result") { 55 | forAll (gcds) { (a: Int, b: Int, z: Int) => 56 | assertTesterPasses{ new GCDTester(a, b, z) } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/IOCompatibility.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | import org.scalatest._ 8 | import org.scalatest.matchers.should.Matchers 9 | 10 | class IOCSimpleIO extends Bundle { 11 | val in = Input(UInt(32.W)) 12 | val out = Output(UInt(32.W)) 13 | } 14 | 15 | class IOCPlusOne extends Module { 16 | val io = IO(new IOCSimpleIO) 17 | io.out := io.in + 1.U 18 | } 19 | 20 | class IOCModuleVec(val n: Int) extends Module { 21 | val io = IO(new Bundle { 22 | val ins = Vec(n, Input(UInt(32.W))) 23 | val outs = Vec(n, Output(UInt(32.W))) 24 | }) 25 | val pluses = VecInit(Seq.fill(n){ Module(new IOCPlusOne).io }) 26 | for (i <- 0 until n) { 27 | pluses(i).in := io.ins(i) 28 | io.outs(i) := pluses(i).out 29 | } 30 | } 31 | 32 | class IOCModuleWire extends Module { 33 | val io = IO(new IOCSimpleIO) 34 | val inc = Wire(chiselTypeOf(Module(new IOCPlusOne).io)) 35 | inc.in := io.in 36 | io.out := inc.out 37 | } 38 | 39 | class IOCompatibilitySpec extends ChiselPropSpec with Matchers with Utils { 40 | 41 | property("IOCModuleVec should elaborate") { 42 | ChiselStage.elaborate { new IOCModuleVec(2) } 43 | } 44 | 45 | property("IOCModuleWire should elaborate") { 46 | ChiselStage.elaborate { new IOCModuleWire } 47 | } 48 | 49 | 50 | class IOUnwrapped extends Module { 51 | val io = new IOCSimpleIO 52 | io.out := io.in 53 | } 54 | 55 | property("Unwrapped IO should generate an exception") { 56 | a [BindingException] should be thrownBy extractCause[BindingException] { 57 | ChiselStage.elaborate(new IOUnwrapped) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/MemorySearch.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | 8 | class MemorySearch extends Module { 9 | val io = IO(new Bundle { 10 | val target = Input(UInt(4.W)) 11 | val en = Input(Bool()) 12 | val done = Output(Bool()) 13 | val address = Output(UInt(3.W)) 14 | }) 15 | val vals = Array(0, 4, 15, 14, 2, 5, 13) 16 | val index = RegInit(0.U(3.W)) 17 | val elts = VecInit(vals.map(_.asUInt(4.W))) 18 | // val elts = Mem(UInt(32.W), 8) TODO ???? 19 | val elt = elts(index) 20 | val end = !io.en && ((elt === io.target) || (index === 7.U)) 21 | when (io.en) { 22 | index := 0.U 23 | } .elsewhen (!end) { 24 | index := index +% 1.U 25 | } 26 | io.done := end 27 | io.address := index 28 | } 29 | 30 | /* 31 | class MemorySearchTester(c: MemorySearch) extends Tester(c) { 32 | val list = c.vals 33 | val n = 8 34 | val maxT = n * (list.length + 3) 35 | for (k <- 0 until n) { 36 | val target = rnd.nextInt(16) 37 | poke(c.io.en, 1) 38 | poke(c.io.target, target) 39 | step(1) 40 | poke(c.io.en, 0) 41 | do { 42 | step(1) 43 | } while (peek(c.io.done) == 0 && t < maxT) 44 | val addr = peek(c.io.address).toInt 45 | expect(addr == list.length || list(addr) == target, 46 | "LOOKING FOR " + target + " FOUND " + addr) 47 | } 48 | } 49 | */ 50 | 51 | class MemorySearchSpec extends ChiselPropSpec { 52 | 53 | property("MemorySearch should elaborate") { 54 | ChiselStage.elaborate { new EnableShiftRegister } 55 | } 56 | 57 | ignore("MemorySearch should return the correct result") { } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests.stage.phases 4 | 5 | 6 | import chisel3.RawModule 7 | import chisel3.stage.ChiselGeneratorAnnotation 8 | import chisel3.stage.phases.{AddImplicitOutputAnnotationFile, Elaborate} 9 | 10 | import firrtl.AnnotationSeq 11 | import firrtl.options.{OutputAnnotationFileAnnotation, Phase} 12 | import org.scalatest.flatspec.AnyFlatSpec 13 | import org.scalatest.matchers.should.Matchers 14 | 15 | class AddImplicitOutputAnnotationFileSpec extends AnyFlatSpec with Matchers { 16 | 17 | class Foo extends RawModule { override val desiredName = "Foo" } 18 | 19 | class Fixture { val phase: Phase = new AddImplicitOutputAnnotationFile } 20 | 21 | behavior of classOf[AddImplicitOutputAnnotationFile].toString 22 | 23 | it should "not override an existing OutputAnnotationFileAnnotation" in new Fixture { 24 | val annotations: AnnotationSeq = Seq( 25 | ChiselGeneratorAnnotation(() => new Foo), 26 | OutputAnnotationFileAnnotation("Bar") ) 27 | 28 | Seq( new Elaborate, phase ) 29 | .foldLeft(annotations)((a, p) => p.transform(a)) 30 | .collect{ case a: OutputAnnotationFileAnnotation => a.file } 31 | .toSeq should be (Seq("Bar")) 32 | } 33 | 34 | it should "generate an OutputAnnotationFileAnnotation from a ChiselCircuitAnnotation" in new Fixture { 35 | val annotations: AnnotationSeq = Seq( ChiselGeneratorAnnotation(() => new Foo) ) 36 | 37 | Seq( new Elaborate, phase ) 38 | .foldLeft(annotations)((a, p) => p.transform(a)) 39 | .collect{ case a: OutputAnnotationFileAnnotation => a.file } 40 | .toSeq should be (Seq("Foo")) 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/Clock.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import scala.language.experimental.macros 6 | import chisel3.internal.Builder.pushOp 7 | import chisel3.internal.firrtl._ 8 | import chisel3.internal.sourceinfo._ 9 | import chisel3.internal.firrtl.PrimOp.AsUIntOp 10 | 11 | object Clock { 12 | def apply(): Clock = new Clock 13 | } 14 | 15 | // TODO: Document this. 16 | sealed class Clock(val width: Width = Width(1)) extends Element { 17 | override def toString: String = s"Clock$bindingToString" 18 | 19 | def cloneType: this.type = Clock().asInstanceOf[this.type] 20 | 21 | private[chisel3] def typeEquivalent(that: Data): Boolean = 22 | this.getClass == that.getClass 23 | 24 | override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { 25 | case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) 26 | case _ => super.badConnect(that)(sourceInfo) 27 | } 28 | 29 | override def litOption: Option[BigInt] = None 30 | 31 | /** Not really supported */ 32 | def toPrintable: Printable = PString("CLOCK") 33 | 34 | /** Returns the contents of the clock wire as a [[Bool]]. */ 35 | final def asBool(): Bool = macro SourceInfoTransform.noArg 36 | def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this.asUInt().asBool() 37 | 38 | override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) 39 | private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, 40 | compileOptions: CompileOptions): Unit = { 41 | this := that.asBool.asClock 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/stage/phases/Convert.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.stage.phases 4 | 5 | import chisel3.experimental.RunFirrtlTransform 6 | import chisel3.internal.firrtl.Converter 7 | import chisel3.stage.ChiselCircuitAnnotation 8 | import firrtl.{AnnotationSeq, Transform} 9 | import firrtl.options.{Dependency, Phase, PreservesAll} 10 | import firrtl.stage.{FirrtlCircuitAnnotation, RunFirrtlTransformAnnotation} 11 | 12 | /** This prepares a [[ChiselCircuitAnnotation]] for compilation with FIRRTL. This does three things: 13 | * - Uses [[chisel3.internal.firrtl.Converter]] to generate a [[FirrtlCircuitAnnotation]] 14 | * - Extracts all [[firrtl.annotations.Annotation]]s from the [[chisel3.internal.firrtl.Circuit]] 15 | * - Generates any needed [[RunFirrtlTransformAnnotation]]s from extracted [[firrtl.annotations.Annotation]]s 16 | */ 17 | class Convert extends Phase with PreservesAll[Phase] { 18 | 19 | override val prerequisites = Seq(Dependency[Elaborate]) 20 | 21 | def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap { 22 | case a: ChiselCircuitAnnotation => 23 | Some(a) ++ 24 | /* Convert this Chisel Circuit to a FIRRTL Circuit */ 25 | Some(FirrtlCircuitAnnotation(Converter.convert(a.circuit))) ++ 26 | /* Convert all Chisel Annotations to FIRRTL Annotations */ 27 | a 28 | .circuit 29 | .annotations 30 | .map(_.toFirrtl) ++ 31 | a 32 | .circuit 33 | .annotations 34 | .collect { 35 | case anno: RunFirrtlTransform => anno.transformClass 36 | } 37 | .distinct 38 | .map { c: Class[_ <: Transform] => RunFirrtlTransformAnnotation(c.newInstance()) } 39 | case a => Some(a) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/test/scala/cookbook/FSM.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package cookbook 4 | 5 | import chisel3._ 6 | import chisel3.util._ 7 | import chisel3.experimental.ChiselEnum 8 | 9 | /* ### How do I create a finite state machine? 10 | * 11 | * Use Chisel StrongEnum to construct the states and switch & is to construct the FSM 12 | * control logic 13 | */ 14 | 15 | class DetectTwoOnes extends Module { 16 | val io = IO(new Bundle { 17 | val in = Input(Bool()) 18 | val out = Output(Bool()) 19 | }) 20 | 21 | object State extends ChiselEnum { 22 | val sNone, sOne1, sTwo1s = Value 23 | } 24 | 25 | val state = RegInit(State.sNone) 26 | 27 | io.out := (state === State.sTwo1s) 28 | 29 | switch (state) { 30 | is (State.sNone) { 31 | when (io.in) { 32 | state := State.sOne1 33 | } 34 | } 35 | is (State.sOne1) { 36 | when (io.in) { 37 | state := State.sTwo1s 38 | } .otherwise { 39 | state := State.sNone 40 | } 41 | } 42 | is (State.sTwo1s) { 43 | when (!io.in) { 44 | state := State.sNone 45 | } 46 | } 47 | } 48 | } 49 | 50 | class DetectTwoOnesTester extends CookbookTester(10) { 51 | 52 | val dut = Module(new DetectTwoOnes) 53 | 54 | // Inputs and expected results 55 | val inputs: Vec[Bool] = VecInit(false.B, true.B, false.B, true.B, true.B, true.B, false.B, true.B, true.B, false.B) 56 | val expected: Vec[Bool] = VecInit(false.B, false.B, false.B, false.B, false.B, true.B, true.B, false.B, false.B, true.B) 57 | 58 | dut.io.in := inputs(cycle) 59 | assert(dut.io.out === expected(cycle)) 60 | } 61 | 62 | class FSMSpec extends CookbookSpec { 63 | "DetectTwoOnes" should "work" in { 64 | assertTesterPasses { new DetectTwoOnesTester } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/DontTouchSpec.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.stage.ChiselStage 7 | 8 | class HasDeadCodeChild(withDontTouch: Boolean) extends Module { 9 | val io = IO(new Bundle { 10 | val a = Input(UInt(32.W)) 11 | val b = Output(UInt(32.W)) 12 | val c = Output(Vec(2, UInt(32.W))) 13 | }) 14 | io.b := io.a 15 | io.c := DontCare 16 | if (withDontTouch) { 17 | dontTouch(io.c) 18 | } 19 | } 20 | 21 | class HasDeadCode(withDontTouch: Boolean) extends Module { 22 | val io = IO(new Bundle { 23 | val a = Input(UInt(32.W)) 24 | val b = Output(UInt(32.W)) 25 | }) 26 | val inst = Module(new HasDeadCodeChild(withDontTouch)) 27 | inst.io.a := io.a 28 | io.b := inst.io.b 29 | val dead = WireDefault(io.a + 1.U) 30 | if (withDontTouch) { 31 | dontTouch(dead) 32 | } 33 | } 34 | 35 | class DontTouchSpec extends ChiselFlatSpec with Utils{ 36 | val deadSignals = List( 37 | "io_c_0", 38 | "io_c_1", 39 | "dead" 40 | ) 41 | "Dead code" should "be removed by default" in { 42 | val verilog = compile(new HasDeadCode(false)) 43 | for (signal <- deadSignals) { 44 | verilog should not include (signal) 45 | } 46 | } 47 | it should "NOT be removed if marked dontTouch" in { 48 | val verilog = compile(new HasDeadCode(true)) 49 | for (signal <- deadSignals) { 50 | verilog should include (signal) 51 | } 52 | } 53 | "Dont touch" should "only work on bound hardware" in { 54 | a [chisel3.BindingException] should be thrownBy extractCause[BindingException] { 55 | ChiselStage.elaborate(new Module { 56 | val io = IO(new Bundle { }) 57 | dontTouch(new Bundle { val a = UInt(32.W) } ) 58 | }) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/TwineConnGen.scala: -------------------------------------------------------------------------------- 1 | package chisel3.twine 2 | 3 | import scala.collection.mutable.{ListBuffer, HashMap, StringBuilder, ArrayBuffer, Set} 4 | import chisel3.internal.sourceinfo.{DeprecatedSourceInfo, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo} 5 | import scala.util.control.Breaks._ 6 | import chisel3.internal.firrtl.PrimOp._ 7 | import chisel3.experimental.BaseModule 8 | import chisel3.internal._ 9 | import chisel3.internal.Builder._ 10 | import chisel3.internal.firrtl._ 11 | import chisel3._ 12 | 13 | object TwineConnGen{ 14 | 15 | // Generate TwineConnection with Module m 16 | def generate(m: TwineModuleBase)(implicit sourceInfo: SourceInfo, 17 | compileOptions: CompileOptions): Any = { 18 | 19 | if(m.isInstanceOf[TwineModuleInternal]) TwineCLConnGen(m.asInstanceOf[TwineModuleInternal]) 20 | 21 | /** 22 | By traversing the connectionMap, we would separate all connections into Lock-step Region, 23 | Decoupled Region, and Cross Region. Lock-step Region need to be reconnected first, 24 | then decoupled region, then Cross Region 25 | */ 26 | for(sub_mod <- m.sub_modules){ 27 | val sync_mods: Set[TwineModuleInternal] = Set() 28 | for(to_mod <- sub_mod.to_modules){ 29 | if(to_mod != m) { 30 | TwineSLConnGen(m, sub_mod, to_mod) 31 | } 32 | for(sync_m <- to_mod.from_modules){ 33 | if(sync_m != m && sync_m != sub_mod){ 34 | if(!sync_mods.contains(sync_m )) sync_mods += sync_m 35 | } 36 | } 37 | } 38 | for(sync_mod <- sync_mods){ 39 | TwineSyncConnGen(m, sub_mod, sync_mod) 40 | } 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/Mux.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import scala.language.experimental.macros 6 | 7 | import chisel3.internal._ 8 | import chisel3.internal.Builder.pushOp 9 | import chisel3.internal.sourceinfo.{SourceInfo, MuxTransform} 10 | import chisel3.internal.firrtl._ 11 | import chisel3.internal.firrtl.PrimOp._ 12 | 13 | object Mux extends SourceInfoDoc { 14 | /** Creates a mux, whose output is one of the inputs depending on the 15 | * value of the condition. 16 | * 17 | * @param cond condition determining the input to choose 18 | * @param con the value chosen when `cond` is true 19 | * @param alt the value chosen when `cond` is false 20 | * @example 21 | * {{{ 22 | * val muxOut = Mux(data_in === 3.U, 3.U(4.W), 0.U(4.W)) 23 | * }}} 24 | */ 25 | def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T] 26 | 27 | /** @group SourceInfoTransformMacro */ 28 | def do_apply[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo, 29 | compileOptions: CompileOptions): T = { 30 | requireIsHardware(cond, "mux condition") 31 | requireIsHardware(con, "mux true value") 32 | requireIsHardware(alt, "mux false value") 33 | val d = cloneSupertype(Seq(con, alt), "Mux") 34 | val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate) 35 | case DontCare => 36 | val dcWire = Wire(d) 37 | dcWire := DontCare 38 | dcWire.ref 39 | case _ => con.ref 40 | } 41 | val altRef = alt match { 42 | case DontCare => 43 | val dcWire = Wire(d) 44 | dcWire := DontCare 45 | dcWire.ref 46 | case _ => alt.ref 47 | } 48 | pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, conRef, altRef)) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/src/main/scala/chisel3/UIntFactory.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3 4 | 5 | import chisel3.internal.firrtl.{IntervalRange, KnownWidth, ULit, UnknownWidth, Width} 6 | import firrtl.Utils 7 | import firrtl.constraint.IsKnown 8 | import firrtl.ir.{Closed, IntWidth, Open} 9 | 10 | // This is currently a factory because both Bits and UInt inherit it. 11 | trait UIntFactory { 12 | /** Create a UInt type with inferred width. */ 13 | def apply(): UInt = apply(Width()) 14 | /** Create a UInt port with specified width. */ 15 | def apply(width: Width): UInt = new UInt(width) 16 | 17 | /** Create a UInt literal with specified width. */ 18 | protected[chisel3] def Lit(value: BigInt, width: Width): UInt = { 19 | val lit = ULit(value, width) 20 | val result = new UInt(lit.width) 21 | // Bind result to being an Literal 22 | lit.bindLitArg(result) 23 | } 24 | /** Create a UInt with the specified range, validate that range is effectively > 0 25 | */ 26 | def apply(range: IntervalRange): UInt = { 27 | // Check is only done against lower bound because range will already insist that range high >= low 28 | range.lowerBound match { 29 | case Closed(bound) if bound < 0 => 30 | throw new ChiselException(s"Attempt to create UInt with closed lower bound of $bound, must be > 0") 31 | case Open(bound) if bound < -1 => 32 | throw new ChiselException(s"Attempt to create UInt with open lower bound of $bound, must be > -1") 33 | case _ => 34 | } 35 | 36 | // because this is a UInt we don't have to take into account the lower bound 37 | val newWidth = if(range.upperBound.isInstanceOf[IsKnown]) { 38 | KnownWidth(Utils.getUIntWidth(range.maxAdjusted.get).max(1)) // max(1) handles range"[0,0]" 39 | } else { 40 | UnknownWidth() 41 | } 42 | 43 | apply(newWidth) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/Decoder.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import org.scalacheck._ 6 | 7 | import chisel3._ 8 | import chisel3.testers.BasicTester 9 | import chisel3.util._ 10 | 11 | class Decoder(bitpats: List[String]) extends Module { 12 | val io = IO(new Bundle { 13 | val inst = Input(UInt(32.W)) 14 | val matched = Output(Bool()) 15 | }) 16 | io.matched := VecInit(bitpats.map(BitPat(_) === io.inst)).reduce(_||_) 17 | } 18 | 19 | class DecoderTester(pairs: List[(String, String)]) extends BasicTester { 20 | val (insts, bitpats) = pairs.unzip 21 | val (cnt, wrap) = Counter(true.B, pairs.size) 22 | val dut = Module(new Decoder(bitpats)) 23 | dut.io.inst := VecInit(insts.map(_.asUInt))(cnt) 24 | when(!dut.io.matched) { 25 | assert(cnt === 0.U) 26 | stop() 27 | } 28 | when(wrap) { 29 | stop() 30 | } 31 | } 32 | 33 | class DecoderSpec extends ChiselPropSpec { 34 | 35 | // Use a single Int to make both a specific instruction and a BitPat that will match it 36 | val bitpatPair = for(seed <- Arbitrary.arbitrary[Int]) yield { 37 | val rnd = new scala.util.Random(seed) 38 | val bs = seed.toBinaryString 39 | val bp = bs.map(if(rnd.nextBoolean) _ else "?") 40 | 41 | // The following randomly throws in white space and underscores which are legal and ignored. 42 | val bpp = bp.map { a => 43 | if (rnd.nextBoolean) { 44 | a 45 | } else { 46 | a + (if (rnd.nextBoolean) "_" else " ") 47 | } 48 | }.mkString 49 | 50 | ("b" + bs, "b" + bpp) 51 | } 52 | private def nPairs(n: Int) = Gen.containerOfN[List, (String,String)](n,bitpatPair) 53 | 54 | property("BitPat wildcards should be usable in decoding") { 55 | forAll(nPairs(4)){ (pairs: List[(String, String)]) => 56 | assertTesterPasses{ new DecoderTester(pairs) } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/BundleWire.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | import chisel3._ 5 | import chisel3.testers.BasicTester 6 | 7 | class Coord extends Bundle { 8 | val x = UInt(32.W) 9 | val y = UInt(32.W) 10 | } 11 | 12 | class BundleWire(n: Int) extends Module { 13 | val io = IO(new Bundle { 14 | val in = Input(new Coord) 15 | val outs = Output(Vec(n, new Coord)) 16 | }) 17 | val coords = Wire(Vec(n, new Coord)) 18 | for (i <- 0 until n) { 19 | coords(i) := io.in 20 | io.outs(i) := coords(i) 21 | } 22 | } 23 | 24 | class BundleToUnitTester extends BasicTester { 25 | val bundle1 = Wire(new Bundle { 26 | val a = UInt(4.W) 27 | val b = UInt(4.W) 28 | }) 29 | val bundle2 = Wire(new Bundle { 30 | val a = UInt(2.W) 31 | val b = UInt(6.W) 32 | }) 33 | 34 | // 0b00011011 split as 0001 1011 and as 00 011011 35 | bundle1.a := 1.U 36 | bundle1.b := 11.U 37 | bundle2.a := 0.U 38 | bundle2.b := 27.U 39 | 40 | assert(bundle1.asUInt() === bundle2.asUInt()) 41 | 42 | stop() 43 | } 44 | 45 | class BundleWireTester(n: Int, x: Int, y: Int) extends BasicTester { 46 | val dut = Module(new BundleWire(n)) 47 | dut.io.in.x := x.asUInt 48 | dut.io.in.y := y.asUInt 49 | for (elt <- dut.io.outs) { 50 | assert(elt.x === x.asUInt) 51 | assert(elt.y === y.asUInt) 52 | } 53 | stop() 54 | } 55 | 56 | class BundleWireSpec extends ChiselPropSpec { 57 | 58 | property("All vec elems should match the inputs") { 59 | forAll(vecSizes, safeUInts, safeUInts) { (n: Int, x: Int, y: Int) => 60 | assertTesterPasses{ new BundleWireTester(n, x, y) } 61 | } 62 | } 63 | } 64 | 65 | class BundleToUIntSpec extends ChiselPropSpec { 66 | property("Bundles with same data but different, underlying elements should compare as UInt") { 67 | assertTesterPasses( new BundleToUnitTester ) 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/MultiIOModule.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chiselTests 4 | 5 | import chisel3._ 6 | import chisel3.testers.BasicTester 7 | 8 | class MultiIOPlusOne extends MultiIOModule { 9 | val in = IO(Input(UInt(32.W))) 10 | val out = IO(Output(UInt(32.W))) 11 | 12 | out := in + 1.asUInt 13 | } 14 | 15 | class MultiIOTester extends BasicTester { 16 | val plusModule = Module(new MultiIOPlusOne) 17 | plusModule.in := 42.U 18 | assert(plusModule.out === 43.U) 19 | stop() 20 | } 21 | 22 | // Demonstrate multiple IOs with inheritance where the IO is assigned to internally 23 | trait LiteralOutputTrait extends MultiIOModule { 24 | val myLiteralIO = IO(Output(UInt(32.W))) 25 | myLiteralIO := 2.U 26 | } 27 | 28 | // Demonstrate multiple IOs with inheritance where the IO is not assigned 29 | // (and must be assigned by what extends this trait). 30 | trait MultiIOTrait extends MultiIOModule { 31 | val myTraitIO = IO(Output(UInt(32.W))) 32 | } 33 | 34 | // Composition of the two above traits, example of IO composition directly using multiple top-level 35 | // IOs rather than indirectly by constraining the type of the single .io field. 36 | class ComposedMultiIOModule extends MultiIOModule 37 | with LiteralOutputTrait with MultiIOTrait { 38 | val topModuleIO = IO(Input(UInt(32.W))) 39 | myTraitIO := topModuleIO 40 | } 41 | 42 | class ComposedMultiIOTester extends BasicTester { 43 | val composedModule = Module(new ComposedMultiIOModule) 44 | composedModule.topModuleIO := 42.U 45 | assert(composedModule.myTraitIO === 42.U) 46 | assert(composedModule.myLiteralIO === 2.U) 47 | stop() 48 | } 49 | 50 | class MultiIOSpec extends ChiselFlatSpec { 51 | "Multiple IOs in MultiIOModule" should "work" in { 52 | assertTesterPasses({ new MultiIOTester }) 53 | } 54 | "Composed MultiIO Modules" should "work" in { 55 | assertTesterPasses({ new ComposedMultiIOTester }) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/scala/chiselTests/OptionBundle.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 OptionBundle(val hasIn: Boolean) extends Bundle { 10 | val in = if (hasIn) { 11 | Some(Input(Bool())) 12 | } else { 13 | None 14 | } 15 | val out = Output(Bool()) 16 | } 17 | 18 | class OptionBundleModule(val hasIn: Boolean) extends Module { 19 | val io = IO(new OptionBundle(hasIn)) 20 | if (hasIn) { 21 | io.out := io.in.get 22 | } else { 23 | io.out := false.B 24 | } 25 | } 26 | 27 | class SomeOptionBundleTester(expected: Boolean) extends BasicTester { 28 | val mod = Module(new OptionBundleModule(true)) 29 | mod.io.in.get := expected.asBool 30 | assert(mod.io.out === expected.asBool) 31 | stop() 32 | } 33 | 34 | class NoneOptionBundleTester() extends BasicTester { 35 | val mod = Module(new OptionBundleModule(false)) 36 | assert(mod.io.out === false.B) 37 | stop() 38 | } 39 | 40 | class InvalidOptionBundleTester() extends BasicTester { 41 | val mod = Module(new OptionBundleModule(false)) 42 | mod.io.in.get := true.B 43 | assert(false.B) 44 | stop() 45 | } 46 | 47 | class OptionBundleSpec extends ChiselFlatSpec with Utils { 48 | "A Bundle with an Option field" should "work properly if the Option field is not None" in { 49 | assertTesterPasses { new SomeOptionBundleTester(true) } 50 | assertTesterPasses { new SomeOptionBundleTester(false) } 51 | } 52 | 53 | "A Bundle with an Option field" should "compile if the Option field is None" in { 54 | assertTesterPasses { new NoneOptionBundleTester() } 55 | } 56 | 57 | "A Bundle with an Option field" should "assert out accessing a None Option field" in { 58 | a [Exception] should be thrownBy extractCause[Exception] { 59 | ChiselStage.elaborate { new InvalidOptionBundleTester() } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/scala/chisel3/aop/AspectLibrary.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package chisel3.aop 4 | 5 | import chisel3.RawModule 6 | import firrtl.options.{OptionsException, RegisteredLibrary, ShellOption} 7 | 8 | /** Enables adding aspects to a design from the commandline, e.g. 9 | * sbt> runMain chisel3.stage.ChiselMain --module --with-aspect 10 | */ 11 | final class AspectLibrary() extends RegisteredLibrary { 12 | val name = "AspectLibrary" 13 | 14 | import scala.reflect.runtime.universe._ 15 | 16 | private def apply(aspectName: String): Aspect[RawModule] = { 17 | try { 18 | // If a regular class, instantiate, otherwise try as a singleton object 19 | try { 20 | val x = Class.forName(aspectName).asInstanceOf[Class[_ <: Aspect[RawModule]]] 21 | x.newInstance() 22 | } catch { 23 | case e: InstantiationException => 24 | val rm = runtimeMirror(getClass.getClassLoader) 25 | val x = rm.staticModule(aspectName) 26 | try { 27 | rm.reflectModule(x).instance.asInstanceOf[Aspect[RawModule]] 28 | } catch { 29 | case _: Exception => throw e 30 | } 31 | } 32 | } catch { 33 | case e: ClassNotFoundException => 34 | throw new OptionsException(s"Unable to locate aspect '$aspectName'! (Did you misspell it?)", e) 35 | case e: InstantiationException => 36 | throw new OptionsException( 37 | s"Unable to create instance of aspect '$aspectName'! (Does this class take parameters?)", e) 38 | } 39 | } 40 | 41 | val options = Seq(new ShellOption[String]( 42 | longOption = "with-aspect", 43 | toAnnotationSeq = { 44 | case aspectName: String => Seq(apply(aspectName)) 45 | }, 46 | helpText = "The name/class of an aspect to compile with (must be a class/object without arguments!)", 47 | helpValueName = Some(".") 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 | --------------------------------------------------------------------------------