もうそこそこ経ってはいるがChiselの3.2-SNAPSHOTがgithubのリリースに上がっている。今回はそれを使うにあたって遭遇したエラーについて。
Chsiel-3.2のSNAPSHOTが公開された
githubのリリースを見ると以下のように今年の3月と5月、それから7月の終わりにそれぞれChiselの3.2のSNAPSHOTが公開されている。
- Release v3.2-032519-SNAPSHOT · freechipsproject/chisel3 · GitHub
- Release v3.2-050719-SNAPSHOT · freechipsproject/chisel3 · GitHub
- Release v3.2-073119-SNAPSHOT · freechipsproject/chisel3 · GitHub
これらのリリースデータを自分のプロジェクトに引っ張りこんでビルドすればChisel3.2を使用することが可能だ。 またこれらのスナップショットデータは"maven"にはあがっていないが、"sonatype-snapshots"には存在しているので"build.sbt"の"chisel3"のバージョンを"3.2-SNAPSHOT"に変更してもOKだ。
ImplicitModuleが、、、消えた??
ここからがこの記事の本題。 それまではその時の最新の安定版"3.1.7"を使用して作業をしていたのだが、何となく"3.2-SNAPSHOT"を使ってみようと思い立ってバージョンを上げてみた。 その時に出くわしのが以下のエラーログ(長いので中間部分は切ってます)。
テストを実行しようとするとElaborateは通るのに実行時にImplicitModule
が無くてエラーになる。
確かに3.2-SNAPSHOTからはchisel3/core/ImplicitModule
が無くなっており、これが原因なのは明らか。
ただ自分の作っているモジュール内にはImplicitModule
を明示的に使用しているモジュールが存在しておらず、どこで参照されているのかが掴めなかった。
[info] [1.734] Done elaborating. Total FIRRTL Compile Time: 955.2 ms [info] DataBufferTester: [info] test.buffer.DataBufferTester *** ABORTED *** [info] java.lang.NoClassDefFoundError: chisel3/core/ImplicitModule [info] at chisel3.iotesters.setupTreadleBackend$.apply(TreadleBackend.scala:141) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply$mcZ$sp(Driver.scala:54) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [info] at logger.Logger$$anonfun$makeScope$1.apply(Logger.scala:138) [info] at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) [info] at logger.Logger$.makeScope(Logger.scala:136) [info] at chisel3.iotesters.Driver$$anonfun$execute$1.apply$mcZ$sp(Driver.scala:39) [info] at chisel3.iotesters.Driver$$anonfun$execute$1.apply(Driver.scala:39) [info] at chisel3.iotesters.Driver$$anonfun$execute$1.apply(Driver.scala:39) [info] ... [info] Cause: java.lang.ClassNotFoundException: chisel3.core.ImplicitModule [info] at java.net.URLClassLoader.findClass(URLClassLoader.java:382) [info] at java.lang.ClassLoader.loadClass(ClassLoader.java:424) [info] at java.lang.ClassLoader.loadClass(ClassLoader.java:357) [info] at chisel3.iotesters.setupTreadleBackend$.apply(TreadleBackend.scala:141) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply$mcZ$sp(Driver.scala:54) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [info] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [info] at logger.Logger$$anonfun$makeScope$1.apply(Logger.scala:138) [info] at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) [info] at logger.Logger$.makeScope(Logger.scala:136) [info] ... [error] java.lang.NoClassDefFoundError: chisel3/core/ImplicitModule [error] at chisel3.iotesters.setupTreadleBackend$.apply(TreadleBackend.scala:141) [error] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply$mcZ$sp(Driver.scala:54) [error] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [error] at chisel3.iotesters.Driver$$anonfun$execute$1$$anonfun$apply$mcZ$sp$1.apply(Driver.scala:39) [error] at logger.Logger$$anonfun$makeScope$1.apply(Logger.scala:138) [error] at scala.util.DynamicVariable.withValue(DynamicVariable.scala:58) [error] at logger.Logger$.makeScope(Logger.scala:136) [error] at chisel3.iotesters.Driver$$anonfun$execute$1.apply$mcZ$sp(Driver.scala:39) 〜中略〜 [error] at java.lang.Thread.run(Thread.java:748) [IJ]sbt:test> [error] (Test / testOnly) java.lang.NoClassDefFoundError: chisel3/core/ImplicitModule
今一度ログを見直していたところ、どうもテスト側のモジュールでエラーが出ていることに気づいた。
DefModule( test.util.WDT@2bbfd7ae,WDT,ArrayBuffer(Port(Clock(IO clock in WDT),Input), Port(Bool(IO reset in WDT),Input), Port(AnonymousBundle(IO io in WDT),Unspecified)), List(DefRegInit(SourceLine(Counter.scala,26,33),UInt<10>(Reg in WDT), Node(Clock(IO clock in WDT)),Node(Bool(IO reset in WDT)),ULit(0,<10>)), DefRegInit(SourceLine(WDT.scala,12,24),Bool(Reg in WDT), Node(Clock(IO clock in WDT)), Node(Bool(IO reset in WDT)),ULit(0,<1>)), DefPrim(SourceLine(Counter.scala,34,24),Bool(OpResult in WDT),eq,WrappedArray(Node(UInt<10>(Reg in WDT)), ULit(998,))), DefPrim(SourceLine(Counter.scala,35,22),UInt<11>(OpResult in WDT),add,WrappedArray(Node(UInt<10>(Reg in WDT)), ULit(1,))), DefPrim(SourceLine(Counter.scala,35,22),UInt<10>(OpResult in WDT),tail,WrappedArray(Node(UInt<11>(OpResult in WDT)), ILit(1))), Connect(SourceLine(Counter.scala,35,13),Node(UInt<10>(Reg in WDT)),Node(UInt<10>(OpResult in WDT))), WhenBegin(SourceLine(Counter.scala,37,21),Node(Bool(OpResult in WDT))), Connect(SourceLine(Counter.scala,37,29),Node(UInt<10>(Reg in WDT)),ULit(0,)), WhenEnd(SourceLine(Counter.scala,37,21),0,false), DefPrim(SourceLine(WDT.scala,17,19),Bool(OpResult in WDT),eq,WrappedArray(Node(UInt<10>(Reg in WDT)), ULit(998,))), WhenBegin(SourceLine(WDT.scala,17,38),Node(Bool(OpResult in WDT))), Connect(SourceLine(WDT.scala,18,13),Node(Bool(Reg in WDT)),ULit(1,<1>)), WhenEnd(SourceLine(WDT.scala,17,38),0,false), DefPrim(SourceLine(WDT.scala,21,10),Bool(OpResult in WDT),eq,WrappedArray(Node(Bool(Reg in WDT)), ULit(0,<1>))), DefPrim(SourceLine(WDT.scala,21,9),Bool(OpResult in WDT),bits,WrappedArray(Node(Bool(IO reset in WDT)), ILit(0), ILit(0))), DefPrim(SourceLine(WDT.scala,21,9),Bool(OpResult in WDT),or,WrappedArray(Node(Bool(OpResult in WDT)), Node(Bool(OpResult in WDT)))), DefPrim(SourceLine(WDT.scala,21,9),Bool(OpResult in WDT),eq,WrappedArray(Node(Bool(OpResult in WDT)), ULit(0,<1>))), WhenBegin(SourceLine(WDT.scala,21,9),Node(Bool(OpResult in WDT))), Printf(SourceLine(WDT.scala,21,9),Node(Clock(IO clock in WDT)),Printables(ListBuffer(PString(Assertion failed: WDT is expired. count = UInt<10>(Reg in WDT) at WDT.scala:21 assert(!expired, s"WDT is expired. count = ${ctr.value}"))))), Stop(SourceLine(WDT.scala,21,9),Node(Clock(IO clock in WDT)),1), WhenEnd(SourceLine(WDT.scala,21,9),0,false), Connect(SourceLine(WDT.scala,23,14),Node(Bool(IO io_expired in WDT)),Node(Bool(Reg in WDT)))) )
以下のval dut
の部分のasInstanceOf[T]
で落ちる。
ここの[T]
は[T <: MultiIOModule]
となっている。
おそらくiotesters
の方でasInstanceOf[T]
を実行した際に、古いMultiIOModule
が参照されており、それが原因でエラーが発生したものと推測。
- TreadleBackend.scala
chisel3.Driver.execute(optionsManager, dutGen) match { case ChiselExecutionSuccess(Some(circuit), _, Some(firrtlExecutionResult)) => val dut = getTopModule(circuit).asInstanceOf[T] firrtlExecutionResult match { case FirrtlExecutionSuccess(_, compiledFirrtl) => (dut, new TreadleBackend(dut, compiledFirrtl, optionsManager = optionsManager)) case FirrtlExecutionFailure(message) => throw new Exception(s"FirrtlBackend: failed firrlt compile message: $message") } case _ => throw new Exception("Problem with compilation") }
それぞれのソースコードを見てみると、Chiselの3.1.7では以下のようにMultiIOModule
はImplicitModule
のエイリアスになっている。
type MultiIOModule = chisel3.core.ImplicitModule
これがChisel3.2-SNAPSHOTだと、以下のようにcore.MultiIOModule
となっている。
type MultiIOModule = chisel3.core.MultiIOModule
以下がcore.MultiIOModule
のソース。
/** Abstract base class for Modules, which behave much like Verilog modules. * These may contain both logic and state which are written in the Module * body (constructor). * This abstract base class includes an implicit clock and reset. * * @note Module instantiations must be wrapped in a Module() call. */ abstract class MultiIOModule(implicit moduleCompileOptions: CompileOptions) extends RawModule { // Implicit clock and reset pins val clock: Clock = IO(Input(Clock())) val reset: Reset = IO(Input(Bool())) // Setup ClockAndReset Builder.currentClockAndReset = Some(ClockAndReset(clock, reset)) private[core] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { implicit val sourceInfo = UnlocatableSourceInfo super.initializeInParent(parentCompileOptions) clock := Builder.forcedClock reset := Builder.forcedReset } }
sbtのevicted
で依存関係を確認してみると、以下のようにコンフリクトが起きていた。
[IJ]sbt:test> evicted [info] Updating ... [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#chisel3_2.11;3.2-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#firrtl_2.11;1.2-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [info] Done updating. [warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings. [warn] Found version conflict(s) in library dependencies; some are suspected to be binary incompatible: [warn] * edu.berkeley.cs:chisel3_2.11:3.2-SNAPSHOT is selected over 3.1.7 [warn] +- diningyo.:test_2.11:0.1.0-SNAPSHOT (depends on 3.1.7) [warn] +- edu.berkeley.cs:chisel-iotesters_2.11:1.2.9 (depends on 3.1.7) [warn] +- diningyo.:test_2.11:3.1.1 (depends on 3.1.7) [warn] * edu.berkeley.cs:firrtl_2.11:1.2-SNAPSHOT is selected over 1.1.7 [warn] +- edu.berkeley.cs:chisel3_2.11:3.2-SNAPSHOT (depends on 1.2-SNAPSHOT) [warn] +- edu.berkeley.cs:firrtl-interpreter_2.11:1.1.7 (depends on 1.1.7) [warn] +- edu.berkeley.cs:chisel-iotesters_2.11:1.2.9 (depends on 1.1.7) [warn] +- edu.berkeley.cs:treadle_2.11:1.0.5 (depends on 1.1.7) [warn] * org.json4s:json4s-native_2.11:3.6.1 is selected over 3.5.3 [warn] +- edu.berkeley.cs:firrtl_2.11:1.2-SNAPSHOT (depends on 3.6.1) [warn] +- edu.berkeley.cs:treadle_2.11:1.0.5 (depends on 3.5.3)
上記のevicted
の情報にも出ているが、原因はiotesters
のバージョンがchisel3.2
が要求するバージョンと違っていたのが原因。
ということで"build.sbt"を修正してiotesters
のバージョンを上げることで対応することにした。
- 修正前
val defaultVersions = Map( "chisel3" -> "3.2-SNAPSHOT", "treadle" -> "1.1-SNAPSHOT", ) //val defaultVersions = Map("chisel3" -> "3.2-SNAPSHOT") lazy val commonSettings = Seq( organization := "diningyo.", autoAPIMappings := true, scalaVersion := "2.11.12", resolvers ++= Seq( Resolver.sonatypeRepo("snapshots"), Resolver.sonatypeRepo("releases") ), crossScalaVersions := Seq("2.11.12", "2.12.6"), scalacOptions := Seq("-deprecation", "-feature") ++ scalacOptionsVersion(scalaVersion.value), javacOptions ++= javacOptionsVersion(scalaVersion.value), libraryDependencies ++= Seq( "com.github.scopt" %% "scopt" % "3.7.0" ), libraryDependencies ++= Seq("chisel3").map { dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) } )
- 修正後
- 以下のように修正することでエラーが解消された。
val defaultVersions = Map( "chisel3" -> "3.2-SNAPSHOT", "treadle" -> "1.1-SNAPSHOT", "chisel-iotesters" -> "1.3-SNAPSHOT" // これを追加して1.3のSNAPSHOTを使用する ) //val defaultVersions = Map("chisel3" -> "3.2-SNAPSHOT") lazy val commonSettings = Seq( organization := "diningyo.", autoAPIMappings := true, scalaVersion := "2.11.12", resolvers ++= Seq( Resolver.sonatypeRepo("snapshots"), Resolver.sonatypeRepo("releases") ), crossScalaVersions := Seq("2.11.12", "2.12.6"), scalacOptions := Seq("-deprecation", "-feature") ++ scalacOptionsVersion(scalaVersion.value), javacOptions ++= javacOptionsVersion(scalaVersion.value), libraryDependencies ++= Seq( "com.github.scopt" %% "scopt" % "3.7.0" ), libraryDependencies ++= Seq("chisel3", "treadle", "chisel-iotesters").map { dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) } )
修正後に再度evicted
を実行すると以下のようにコンフリクトの情報が表示されず、依存関係の解決が出来ていることが確認できた。
evicted [info] Updating ... [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#chisel3_2.11;3.2-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#firrtl_2.11;1.2-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#chisel-iotesters_2.11;1.3-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#firrtl-interpreter_2.11;1.2-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [warn] Resolving a snapshot version. It's going to be slow unless you use `updateOptions := updateOptions.value.withLatestSnapshots(false)` options. [info] Out of 1 candidates we found for edu.berkeley.cs#treadle_2.11;1.1-SNAPSHOT in sonatype-snapshots, we are choosing sonatype-snapshots. [info] Done updating. [success] Total time: 13 s, completed 2019/08/04 13:59:09
この状態でテストを実行すると正常に動作した。
おまけ ~ 他のプロジェクトでもアップデート時に別のエラーが。。
別のプロジェクトでも3.2-SNAPSHOTに切り替えると、上で紹介したのと同じ理由で以下のようなエラーにも遭遇した(因みにこのプロジェクトは前回の記事のもの)。
[info] Compiling 1 Scala source to /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/target/scala-2.11/test-classes ... [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:72:5: Symbol 'term chisel3.package.experimental' is missing from the classpath. [error] This symbol is required by 'type chisel3.iotesters.Driver.T'. [error] Make sure that term experimental is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. [error] A full rebuild may help if 'Driver.class' was compiled against an incompatible version of chisel3.package. [error] iotesters.Driver.execute( [error] ^ [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:74:16: Symbol 'type <none>.experimental.MultiIOModule' is missing from the classpath. [error] This symbol is required by 'type chisel3.iotesters.PeekPokeTester.T'. [error] Make sure that type MultiIOModule is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. [error] A full rebuild may help if 'PeekPokeTester.class' was compiled against an incompatible version of <none>.experimental. [error] c => new PeekPokeTester(c) { [error] ^ [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:72:22: inferred type arguments [SimDTM] do not conform to method execute's type parameter bounds [T <: chisel3.experimental.MultiIOModule] [error] iotesters.Driver.execute( [error] ^ [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:73:29: type mismatch; [error] found : () => SimDTM [error] required: () => T [error] Array("-tgvo=on"), () => new SimDTM(20, true)) { [error] ^ [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:76:29: not found: value t [error] println(f"step = $t") [error] ^ [error] /home/diningyo/prj/study/2000_chisel/500_learning-chisel3/subprj/sim-wdt/src/test/scala/BaseSimDTM.scala:77:11: not found: value step [error] step(1) [error] ^ [error] 6 errors found [error] (Test / compileIncremental) Compilation failed [error] Total time: 10 s, completed 2019/08/04 13:12:09
こちらも上記のiotesters
の更新で正常に動作するのを確認済み↓。
> test [info] [0.002] Elaborating design... [info] [0.146] Done elaborating. Total FIRRTL Compile Time: 446.8 ms file loaded in 0.080993408 seconds, 24 symbols, 20 statements [info] [0.001] SEED 1564894676648 [info] [0.001] step = 0 [info] [0.002] step = 1 [info] [0.003] step = 2 [info] [0.003] step = 3 [info] [0.004] step = 4 [info] [0.005] step = 5 [info] [0.006] step = 6
Chisel3.2(のスナップショット)を使おうとして、少しハマった話でした。 これから試してみようかなーーとお考えの方はバージョンにはご注意ください。