Chisel3.4.0の変更点確認の3回目。今回は#1550のio
がdeprecated指定に変更された件の影響を確認する。
(#1550) Deprecate Module.io and BlackBox.io
PRの内容自体は、タイトルそのままでModule.io
/BlackBox.io
がdeprecated
に指定された、というもの。
ただModule
/BlackBox
クラスはChiselでモジュールを作る際のベースになるもので、雛形の様に次のようなモジュールの形を作ってきたので、影響が大きいのでは??となったので、ちょっとしっかり確認してみる。
- Chiselのモジュールの雛形
import chisel3._ import chisel3.util._ class <モジュール名> extends Module { val io = IO(new Bundle { // <-- このioがdeprecatedになっている。 <ポート宣言> }) }
実際にPRで修正されたソースコードは次のようなもので、確かにdeprecated
扱いになっている。
// IO for this Module. At the Scala level (pre-FIRRTL transformations), // connections in and out of a Module may only go through `io` elements. @deprecated("Removed for causing issues in Scala 2.12+. You remain free to define io Bundles " + "in your Modules, but you cannot rely on an io field in every Module. " + "For more information, see: https://github.com/freechipsproject/chisel3/pull/1550.", "Chisel 3.4" ) def io: Record
これコメントにもあるとおりで、実際に次のバージョンとかで削除されると、モジュールにio
という変数が無くてもOKになる(RawModule
使うのと変わらん状態)。
変更された理由
なぜ今回の修正が入ったかについては、PRのコメントを読むと書いてあった。
I was experimenting with some stuff in Scala 2.13 and realized that -Xsource:2.11 is no longer supported in 2.13. In fact, it was never recommended as an option to Scalac for anything but debugging, let alone our recommended way of supporting Scala 2.12.
現在のChiselはScala 2.12上で動かす場合には、-Xsource:2.11
の指定を入れて、動作しているのだが、この指定がScala 2.13からは使えなくなってしまう。
そのため、残された方法として-Xsoucrce:2.11
の指定を市内状態でScala 2.12をサポートする必要が出たということらしい。
ここで気になるのが、どのような記述がScala 2.12では動作しなかったのか、ということなのだが、それについてのコメントが次のもの。
For a long time, we thought the issue only had to do with structural typing. This was incorrect, there were actually 2 different problems: 1. Structural Typing - formerly unsupported in Scala 3, now supported, it always worked in Scala 2.12/13 1. Type Inference for overridden definitions defaults to overridden type (as opposed to overriding type) - Strict in Scala 3, weaker in Scala 2.12/13
構造的型付けと、継承元のデフォルト型をオーバーライドしたときの挙動が問題だった、らしい。
具体的には、モジュール宣言の際に行っているio
の宣言部分が該当している。
現在は
-Xsource
を使って次のように書けているscala class MyModule extends Module { val io = IO(new Bundle { ... }) }
-Xsource
無しのScala 2.12だと、次のようにIO用の型の定義が必要になる。(無いとエラー)scala class MyModule extends Module { class MyModuleIntf extends Bundle { ... } val io = IO(new MyModuleIntf) }
さらにScala 3からは型の明示が必要になる(らしい)
```scala class MyModule extends Module { class MyModuleIntf extends Bundle { ... } val io: MyModuleIntf = IO(new MyModuleIntf) }
で、これが起きる原因というのがModule
で宣言されているval io: Record
という宣言にあるため、この指定を廃止しようというこになったようだ。
影響範囲
単純に冒頭に記載したval io
のdeprecated
指定の変更だけだと、いろんなシチュエーションでdeprecated
の警告が発生しそうだが、実際にはあんまり発生はしなかった。
というのも、次のように対策のための実装がなされており、ある程度、というかかなりのケースで警告が発生しないようになっている。
// Private accessor to reduce number of deprecation warnings private[chisel3] def _io: Record = io // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(_io)
この対策のおかげで、次のような基本的な使い方では警告は発生しない。
class MyModule extends Module { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) io.out := io.in }
今回の修正でio
にまつわるdeprecated
の警告が発生するのは、次のコードのように、Module.io
を直接参照するケース。
このコードではDeprecatedIOGetsWarning
というモジュール内で、Module
クラスを引数に取るconnect
というメソッドが定義されている。
この場合、connect
メソッドにModule
を継承した自前のクラスを渡しても、connect
メソッドでは継承元のModule
クラスが見えるため、deprecated
に関する警告が発生する。
import chisel3._ import chisel3.util._ class DeprecatedIO extends Module { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) io.out := !io.in } class DeprecatedIOGetsWarning extends Module { val io = IO(new Bundle { val in = Input(Bool()) val out = Output(Bool()) }) val m = Module(new DeprecatedIO) def connect(src: Module, dst: Module): Unit = { dst.io <> src.io // 警告が発生 // 次のようにasInstanceOfを使うと警告は消える //dst.asInstanceOf[DeprecatedIO].io <> src.asInstanceOf[DeprecatedIOGetsWarning].io } connect(this, m) } object ElaborateDeprecatedIO extends App { println(chisel3.stage.ChiselStage.emitVerilog(new DeprecatedIO)) println(chisel3.stage.ChiselStage.emitVerilog(new DeprecatedIOGetsWarning)) }
- 発生する警告
[warn] /home/diningyo/workspace/study/2000_chisel/500_learning-chisel3/ subprj/chisel-3.4.x/src/main/scala/DeprecatedIO.scala:23:9: method io in class LegacyModule is deprecated (since Chisel 3.4): Removed for causing issues in Scala 2.12+. You remain free to define io Bundles in your Modules, but you cannot rely on an io field in every Module. For more information, see: https://github.com/freechipsproject/chisel3/pull/1550. [warn] dst.io <> src.io // 警告が発生
Module.io
を直接触らなければOKなので、上記のconnect
メソッドにおいても、asInstanceOf
を使って元のクラスに戻せば警告は消すことができる。
まとめ
PRのタイトル見たときは、「影響範囲デカくない??」と思ったけど、既存のモジュールについては、さほど気にしなくても良さそう。
今後という点で考えると、実際にval io
が削除されるとModule
を継承したクラスにio
が存在する保証は無くなる。
そのため、自分以外の人が作ったモジュールを見る時にはIOポートの宣言が何になっているかに少しだけ注意が必要かも(とはいえ、IO()
で囲われていることは変わらないので、これもそんなに気にならない)。