ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

Chisel3.2-SNAPSHOTを試した時に遭遇したエラー

スポンサーリンク

もうそこそこ経ってはいるがChiselの3.2-SNAPSHOTがgithubのリリースに上がっている。今回はそれを使うにあたって遭遇したエラーについて。

Chsiel-3.2のSNAPSHOTが公開された

githubのリリースを見ると以下のように今年の3月と5月、それから7月の終わりにそれぞれChiselの3.2のSNAPSHOTが公開されている。

  1. Release v3.2-032519-SNAPSHOT · freechipsproject/chisel3 · GitHub
  2. Release v3.2-050719-SNAPSHOT · freechipsproject/chisel3 · GitHub
  3. 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が参照されており、それが原因でエラーが発生したものと推測。

    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では以下のようにMultiIOModuleImplicitModuleエイリアスになっている。

    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(のスナップショット)を使おうとして、少しハマった話でした。 これから試してみようかなーーとお考えの方はバージョンにはご注意ください。