ChiselからVerilogを生成すると、配列参照の記述は最終的に除去され、とんでもないVerilogが生成されることはよくある。 これをVerilogでそのまま配列で出力する方法を探しているのだが、試行錯誤でなかなかうまく進まない。
まず、passes.RemoveAccesses
パスを除去すると、配列アクセスが除去出るが、それだけで話は終わらない。
例えば、入力ポートに対してVecを使っているとVerilog生成時にVecがすべて分解されてしまう。
すると、配列参照のために残していたin_a[in]
というコードに対して、in_a
がin_a_0
, in_a_1
, in_a_2
, in_a_3
などに分解されてしまい名前参照に失敗する。
これはどうすればいいのだろう?
まず、InferTypes
のパスにprintfを大量に挿入していくと、このあたりで配列参照を個々の信号に分解していることが分かる。
firrtl/src/main/scala/firrtl/passes/InferTypes.scala
val portsx = m.ports flatMap { p => val exps = create_exps(WRef(p.name, p.tpe, PortKind, to_flow(p.direction))) val names = exps map loweredName renameExps(renames, p.name, p.tpe) (exps zip names) map { case (e, n) => Port(p.info, n, to_dir(flow(e)), e.tpe) } }
このFIRの回路が、
circuit VecModules : module VecModules : input in : UInt<1>[4] input sel : UInt<2> output out : UInt<1> skip out <= in[sel]
このように分解されてしまう。
circuit VecModules : module VecModules : input in_0 : UInt<1> input in_1 : UInt<1> input in_2 : UInt<1> input in_3 : UInt<1> input sel : UInt<2> output out : UInt<1> skip out <= in[sel]
これを防ぐためには、どうにかしてVecの分解を防ぐ方法を見つけなければならない。とりあえず、上記のexps
がどのようになっているかダンプしてみると、
Vector(WSubIndex(WRef(in,VectorType(UIntType(IntWidth(1)),4),PortKind,SourceFlow),0,UIntType(IntWidth(1)),SourceFlow), WSubIndex(WRef(in,VectorType(UIntType(IntWidth(1)),4),PortKind,SourceFlow),1,UIntType(IntWidth(1)),SourceFlow), WSubIndex(WRef(in,VectorType(UIntType(IntWidth(1)),4),PortKind,SourceFlow),2,UIntType(IntWidth(1)),SourceFlow), WSubIndex(WRef(in,VectorType(UIntType(IntWidth(1)),4),PortKind,SourceFlow),3,UIntType(IntWidth(1)),SourceFlow) )
うーん、4つに分解されたけど個々の要素が複雑すぎんかね? とりあえず、分解するコードを削ってみる。
firrtl/src/main/scala/firrtl/Utils.scala
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala index 4bf2d14d..957fb200 100644 --- a/src/main/scala/firrtl/Utils.scala +++ b/src/main/scala/firrtl/Utils.scala @@ -241,7 +241,8 @@ object Utils extends LazyLogging { case (_: GroundType) => Seq(ex) case t: BundleType => t.fields.flatMap(f => create_exps(WSubField(ex, f.name, f.tpe,times(flow(ex), f.flip)))) - case t: VectorType => (0 until t.size).flatMap(i => create_exps(WSubIndex(ex, i, t.tpe,flow(ex)))) + // case t: VectorType => (0 until t.size).flatMap(i => create_exps(WSubIndex(ex, i, t.tpe,flow(ex)))) + case t: VectorType => Seq(ex) } }
とりあえずこの状態のままキープする。
circuit VecModules : module VecModules : input in : UInt<1>[4] input sel : UInt<2> output out : UInt<1> out <= in[sel]
今度はこのエラーだ。これはなんだろう?
======== Starting Transform DeadCodeElimination ======== Exception in thread "main" firrtl.FirrtlInternalException: Internal Error! Please file an issue at https://github.com/ucb-bar/firrtl/issues at firrtl.Utils$.error(Utils.scala:424) at firrtl.Utils$.throwInternalError(Utils.scala:164) at firrtl.transforms.DeadCodeElimination.$anonfun$setupDepGraph$20(DeadCodeElimination.scala:143) at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62) at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55) at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49) at firrtl.transforms.DeadCodeElimination.setupDepGraph(DeadCodeElimination.scala:141) ...