FIRRTLの変換フローについて調査した。ソースコードを読みながら各Passが何を実行しているのかを確認していく。
実行方法としては、
./utils/bin/firrtl -td regress -i ./regress/simple_test.fir -X sverilog -ll trace 2>&1 | tee simple_test.log
として、出力されるログを見ながらPassを確認していく。
ChirrtlToHighFirrtlCheckChirrtlCheckHighFormLikeに実体が存在する。Circuit内のTopModuleを探す。
CInferTypessrc/main/scala/firrtl/passes/InferTypes.scala- 上位から順に伝搬できる型を下位に伝搬させる。
CInferMDir$src/main/scala/firrtl/passes/Resolves.scala- ポートの方向を伝搬させる?
RemoveCHIRRTLsrc/main/scala/firrtl/passes/RemoveCHIRRTL.scala- CHIRRTL と呼ばれるChiselのHigh Level Immediate Representationを変換する。
IRToWorkingIRToWorkingIRsrc/main/scala/firrtl/passes/Passes.scala- IRのノードからFirrtlNodeの形式に変換する。
ResolveAndCheckCheckHighForm$src/main/scala/firrtl/passes/Checks.scala- ルール違反の制約を探す?
ResolveKinds$src/main/scala/firrtl/passes/Resolves.scala- ポートの名前から型に対するテーブルを作っていく。
InferTypessrc/main/scala/firrtl/passes/InferTypes.scalaCInferTypeと同様だが、FirrtlNodeに対して処理を実行する。
CheckTypessrc/main/scala/firrtl/passes/Checks.scala- 各構文に対して、有効な型が使われているかをチェックする。例えば演算に対して有効な型のノードが適用されているか。
Uniquifysrc/main/scala/firrtl/passes/Uniquify.scala- 変数名の変換により別の変数と衝突してしまうことを防ぐ。例えば、
a[0]をa_0に変換すると元々a_0だったものにぶつかってしまう。なのでこの場合はa__0などに変換する?
ResolveKindssrc/main/scala/firrtl/passes/Resolves.scala- ポートの名前から型に対するテーブルを作っていく。
InferTypesResolveFlowssrc/main/scala/firrtl/passes/Resolves.scala- 配線同士のフローを構築する。例えば
Flipなどは方向を逆転させて本来の方向へ戻す。
CheckFlowssrc/main/scala/firrtl/passes/Checks.scalaResolveFlowsの解決後のチェックを行う。
InferWidthssrc/main/scala/firrtl/passes/InferWidths.scala- トップ階層から順に、配線のビット幅の推論を行っていく。
CheckWidthssrc/main/scala/firrtl/passes/CheckWidths.scala- ビット幅の矛盾をチェックする。例えば、代入時のビット幅に矛盾がないか、など。
InferResetssrc/main/scala/firrtl/transforms/InferResets.scala- リセット信号を推論させる。
DedupModulesHighFirrtlToMiddleFirrtlPullMuxessrc/main/scala/firrtl/passes/Passes.scalaSubFieldやSubIndexなどの型に対して、MuxやValidIfが使用されていると、この順序を変える。
ReplaceAccessessrc/main/scala/firrtl/passes/ReplaceAccesses.scalaWSubAccess(index)で、indexが定数の場合はWSubIndexに変換する。
ExpandConnectssrc/main/scala/firrtl/passes/Passes.scala- 配列や構造体について、Connect文を各要素に展開する。
Uniquifysrc/main/scala/firrtl/passes/Uniquify.scala- 変数名の変換により別の変数と衝突してしまうことを防ぐ。例えば、
a[0]をa_0に変換すると元々a_0だったものにぶつかってしまう。なのでこの場合はa__0などに変換する?
ExpandWhenssrc/main/scala/firrtl/passes/ExpandWhens.scala- Whenを分解してMuxに変換する。
CheckInitializationsrc/main/scala/firrtl/passes/CheckInitialization.scala- 完全に初期化されていない変数を探してエラーを出力する。
ResolveKindsInferTypesCheckTypesCheckResetsResolveFlowsInferWidthsCheckWidthsConvertFixedToSIntsrc/main/scala/firrtl/passes/ConvertFixedToSInt.scalaFixedInt型をSInt型に変換する。
ZeroWidthsrc/main/scala/firrtl/passes/ZeroWidth.scala- ビット幅がゼロのメモリを除去する。なんでそんなものが生成されるのか謎だが...
InferTypes
MiddleFirrtlToLowFirrtlLowerTypesResolveKindsInferTypesResolveFlowsInferWidthsLegalizesrc/main/scala/firrtl/passes/Passes.scala- 演算に際し型のLegalizeなどを行う。
RemoveResetsrc/main/scala/firrtl/transforms/RemoveReset.scala- Registerの定義されていないモジュールに対してResetの除去を行う。
CheckCombLoopssrc/main/scala/firrtl/transforms/CheckCombLoops.scala- Combinational Loopの検出を行う。
RemoveWiressrc/main/scala/firrtl/transforms/RemoveWires.scala- 不要な信号を除去する。
LowFirrtlOptimizationRemoveValidIfsrc/main/scala/firrtl/passes/RemoveValidIf.scalaValidIfを除去して分解する。
ConstantPropagationsrc/main/scala/firrtl/transforms/ConstantPropagation.scala- 定数の伝搬を行う。
PadWidthssrc/main/scala/firrtl/passes/PadWidths.scala- 自動的なビット拡張に対する処理を行う。
ConstantPropagationLegalizeVerilogMemDelayssrc/main/scala/firrtl/passes/memlib/VerilogMemDelays.scala- メモリモジュールに対する遅延の挿入?
ConstantPropagationSplitExpressionssrc/main/scala/firrtl/passes/SplitExpressions.scala- 複数の式などをそれぞれの式に分解する。
CombineCatssrc/main/scala/firrtl/transforms/CombineCats.scala- 複数のCatsをマージする。
CommonSubexpressionEliminationsrc/main/scala/firrtl/passes/CommonSubexpressionElimination.scala- 共通の式を除去する?
SystemVerilogEmitterBlackBoxSourceHelperReplaceTruncatingArithmeticFlattenRegUpdateVerilogModulusCleanup$VerilogRenameVerilogPrep$AddDescriptionNodes