Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CSR を自動生成する!

CSR を自動生成する!

Taichi Ishitani

November 09, 2019
Tweet

More Decks by Taichi Ishitani

Other Decks in Technology

Transcript

  1. 目次 ❏ 自己紹介 ❏ CSRの実装、どうしてますか? ❏ RgGenご紹介 ❏ まずはデモ! ❏

    ざっくりとした構造 ❏ レジスタマップ ❏ 生成 RTL を少し詳しく ❏ ユーザー拡張について少々 ❏ 最後にお願い 2
  2. 自己紹介 • 石谷太一(イシタニタイチ) ◦ GitHub https://github.com/taichi-ishitani ▪ 自作 AXI VIP

    とか、自作 NoC もある ので、見てみて! ◦ Twitter @taichi600730 • SystemVerilog / Ruby 歴 11年とちょっと ◦ SystemVerilog で RTL 書いたり、UVM で検 証環境作ったり ◦ ツールのお気持ちを察する能力の高まりを感 じる日々を送っています 3 • 社歴 ◦ 2008.4 - 2011.10 IBEXテクノロジー株式会 社 ▪ 川崎奥地の受託兼放送機器メーカー ▪ SystemVeriloger 人生の始まり ◦ 2011.11 - 2012.1 インベンチュア株式会社 ▪ 日系 CAD 屋の IP 子会社 ▪ 入社3ヶ月後に買収される ◦ 2012.2 - 2017.3 日本シノプシス合同会社 ▪ UVM とか PCIe と戯れる ◦ 2017.4 - 現在 株式会社PEZY Computing ▪ 入社6ヶ月に事件発生 ▪ まだまだ元気です ▪ 最近、求人情報が更新されました
  3. CSRの実装、どうしてますか? 多分、こんな流れ・・・ 1. CSR の仕様を考えて、Excel でレジスタマップを書く 2. レジスタマップを元に RTL をコーディングする

    3. その他の関連するコードを書く ◦ 全部読み書きするテスト ◦ 社内用 Wiki 4. レジスタが足りないようなら、レジスタマップを更新する 5. RTL 等に変更を反映する 4
  4. CSRの実装、どうしてますか? • 基本的には難しくはない ◦ アドレスをデコードして、レジスタを読み書きす るだけ • ただただ面倒 ◦ 微妙な違いが多く、間違いやすい

    ▪ オフセットアドレス、ビット位置とか幅 ◦ とにかく数が多い ◦ 単純な読み書きだけではない ▪ 1書き込みクリアとか、自動クリアとか • 書くのは、RTL だけではない ◦ 全部読み書きするテストとか、シミュレーション モデルとか、Wiki とか ◦ RTL と同じ用に、単調 & 面倒 5 • レジスタマップと、実装が合わないぞ・・・ ◦ 仕様とかドキュメントの更新は後回しにされが ち • レジスタマップを神様にして、自動生成する のが幸せ という訳で、CSR 自動生成ツール RgGen を作り ました! ❖ 2009年に初代を作り始めてから、現在で 4 代目 ❖ 10 年間、作っては作り直して、を繰り返してい る
  5. RgGenご紹介 • レジスタマップから、CSR関連のファイルを生成するツールです ◦ GitHubで公開中 https://github.com/rggen/rggen ◦ Ruby で実装 (Viva

    メタプログラミング! ) • 以下のファイルを生成します ◦ RTL (SystemVerilog) ◦ シミュレーション用モデル (UVM RAL) ◦ Wiki ドキュメント (Markdown) • レジスタマップは、人間様が (たぶん) 読めるフォーマットです ◦ 対応フォーマット ▪ Ruby (レジスタマップを書くための DSLを定義しました) ▪ YAML/JSON ▪ Excel/LibreOffice Calc/CSV ◦ XML (IP-XACT) とか書きたくないよね・・・ 6
  6. RgGenご紹介 • 生成できるレジスタ、ビットフィールドの型は (たぶん) 多いです ◦ レジスタ ▪ 外部接続とか、間接アクセスも対応 ◦

    ビットフィールド ▪ 今現在 21 種類 ▪ https://github.com/rggen/rggen/wiki/Register-Map-Specifications を参照 • 標準的なホストIFプロトコルに対応 ◦ AMBA APB/AXI4 Lite ◦ Avalon-MM はそのうち・・・ • ユーザー環境に合わせて、拡張することも可能 ◦ ビットフィールド型の追加とか、ホスト IFのプロトコルの追加とか ◦ VHDL対応など、独自の生成器を作ることも可能 (ただし Ruby が書ければ・・・) 7
  7. まずはデモ! • インストール ◦ Ruby のパッケージ管理コマンドを叩くだけで OK ◦ $ gem

    install rggen • 入力ファイル ◦ コンフィグレーションファイル ▪ バス幅や、ホストIFのプロトコルを設定 するためのファイル ◦ レジスタマップ ▪ CSR の仕様を記述したファイル ◦ サンプルは GitHub にあります ▪ https://github.com/rggen/rggen-sam ple 8 • 生成! ◦ 実行コマンド rggen に食わせるだけ ◦ 代表的なオプション ▪ -c • コンフィグレーションファイルの パスを指定 ▪ -o • 出力ディレクトリを指定 ◦ $ rggen -c config.yml -o out block_0.yml bock_1.yml
  8. ざっくりとした構造 RgGen Config Register Map Config Object Register Map Object

    SV RTL Generator UVM RAL Generator Markdown Generator SV RTL UVM RAL MD Wiki • 入力ファイルのパース ◦ 連想配列っぽいデータ構造に展開 ▪ 値と位置情報を保持するだけ ▪ 後段の処理から、入力フォーマットに 関する処理を分離 ◦ Config/Register Map Object 生成 ▪ パースした値へのアクセッサや、便利 API を提供 ▪ 生成時に、エラーチェックも行う • ファイルの生成 ◦ Config/Register Map Object に従って、テン プレートを処理 ◦ テンプレートから生成したコード片を組み上げ て、ファイルを書き出す ◦ ジェネレータを追加することで、他のファイル を書き出すことも可能 9
  9. レジスタマップ (基本) • Ruby / YAML / JSON / Excel

    でレジスタマップを記述します ◦ 今回は YAML で説明 • YAML の基本 ◦ インデントを使って、階層構造を表現 ◦ key: value ▪ 連想配列の要素 ◦ - value ▪ 配列の要素 ◦ 連想配列、配列は入れ子にすることが出来る • 4層の階層構造になっている ◦ register map / register block / register / bit field ◦ 連想配列と配列を組み合わせて、各階層を表現 ▪ 自身の属性: 連想配列の各要素 ▪ 下位階層: 連想配列にぶら下がる配列 register_blocks : - name: foo_0 registers: - name: foo_0_0 bit_fields: - { name: foo_0_0_0 } - { name: foo_0_0_1 } - name: foo_0_1 bit_fields: - { name: foo_0_1_0 } - { name: foo_0_1_1 } 10
  10. レジスタマップ(register block の記述) • name ◦ レジスタブロックの名前 ◦ モジュールやモデルの識別子になる •

    byte_size ◦ レジスタブロックの大きさをバイト単位で指定 ◦ オフセットアドレスの幅を決定 • registers ◦ register の定義を纏めた配列 11
  11. レジスタマップ (register の記述) • name ◦ レジスタの名前 • offset_address ◦

    オフセットアドレス ◦ 全体のアクセス属性が、read only と write only であれば、同じアドレス領域を共有可能 • size ◦ アドレス方向の大きさ (個数) を指定 ◦ 一次元配列はもちろん、多次元配列も可 ◦ ビットフィールド方向の大きさは、配下のビット フィールドの大きさで決まる ▪ バス幅以上のレジスタを定義できる ▪ foo_upper/foo_lower のように、分け なくても良い • type ◦ レジスタの型を指定 ▪ 指定がない場合は、普通のレジスタ ◦ external ▪ offset_address/sizeで指定した範囲 に、他のモジュールを繋げる ◦ indirect ▪ 間接アクセス用レジスタ ▪ アドレスの他に、インデックス用のビッ トフィールドを指定 ▪ 配列レジスタを、単一のアドレス領域 に配置 ▪ 複数のレジスタを、同一アドレス領域 に配置 • bit_fields ◦ ビットフィールドの定義を纏めた配列 12
  12. レジスタマップ (bit fieldの記述) • name ◦ ビットフィールドの名前 ◦ レジスタとビットフィールド名を結合させたものが、ポート名等になる •

    bit_assignment ◦ ビット割当を連想配列で指定 ◦ lsb/width/sequence_size/step ▪ sequnce_size: 繰り返しの数 ▪ step: 次の要素へのオフセット ◦ 幅や開始位置等に制限なし ▪ バス幅を超えるビットフィールドを定義することができる ◦ 互い違いになったビット割当も定義できる ▪ lsb: 0 , width: 8, sequence_size: 4, step: 16 / lsb: 8 , width: 8, sequence_size: 4, step: 16 ▪ [63:56] / [55:48] / [47:40] / [39:32] / [31:24] / [23:16] / [15:8] / [7:0] 13
  13. レジスタマップ (bit fieldの記述) 14 • type ◦ ビットフィールドの型を指定 ▪ rw:

    普通のRWビットフィールド ▪ ro: リードオンリー ▪ w1c: 1書き込みクリア ◦ 指定できる型は Wiki を参照 ▪ https://github.com/rggen/rggen/wiki/Register-Map-Specifications • initial_value ◦ 初期値 • reference ◦ 参照ビットフィールド ◦ 指定がある場合、マスクやクリア信号、ラッチ信号等として使われる • comment ◦ ビットフィールドの説明を記述 ◦ Markdown に反映される
  14. 生成 RTL を少し詳しく • モジュールインスタンスのみで、論理は殆ど なし ◦ 生成が面倒な部分は、共通モジュール側に実 装 ◦

    https://github.com/rggen/rggen-sv-rtl ◦ 生成 RTL を使う際に、一緒にコンパイル • 基本的には SystemVerilog 中で使う前提 ◦ インターフェースとか、多次元配列とか ◦ 従来の Verilog っぽく見える RTL を生成する 機能もある ▪ インターフェースを展開 ▪ 多次元配列を 1 次元配列化 ◦ VHDL 中でも使える・・・はず • バックドアアクセスに対応 ◦ 直接レジスタを読み書きする ▪ 書き込み: 1サイクル ▪ 読み出し: 即時 ◦ シミュレーションの高速化 • サンプルのテストベンチもあるので、動作確 認の参考にどうぞ ◦ https://github.com/rggen/rggen-sample-test bench ◦ UVM + UVM RAL + AMBA VIP (APB / AXI4-Lite) 15
  15. ユーザー拡張について少々 • 使用環境に合わせて、拡張することが出来 る ◦ ビットフィールド型の追加 ◦ ホスト IF のプロトコルの追加

    • プラグインとして、ユーザー拡張を実装 ◦ テンプレートがあるので、ここから開始 ▪ https://github.com/rggen/rggen-plugi n-template ◦ ビットフィールド型の追加ぐらいなら、 Ruby に詳しくなくても大丈夫・・・ ▪ Qiita に追加方法を載せました ▪ https://qiita.com/taichi-ishitani/items/ d89738b5376503c813d8 ▪ https://github.com/rggen/rggen-sam ple-plugin ◦ 社内用のプラグインを実装し、実運用中 16 • オレオレジェネレータの追加もサポート ◦ 他言語対応など ◦ 既存のジェネレータも同じ機能を使って、実装 している ◦ さすがに、Ruby チョットワカルでないと、厳し いと思う
  16. 最後にお願い • ぜひ使ってみてください! ◦ Quartus で食えるか未確認なので、確認してほしいです ◦ できれば、フィードバックがほしいです ◦ ほかに生成したいファイルはありますか?

    • Help Wanted ! ◦ VHDL 分かる人 ◦ Bluespec System Verilog 分かる人 ◦ SystemRDL 分かる人 ◦ Avalon-MM 分かる人 RgGen を、何卒、よろしくお願いします m(_ _)m 17
  17. リンク • GitHub ◦ https://github.com/rggen/rggen ◦ https://github.com/rggen/rggen-core ◦ https://github.com/rggen/rggen-default-register-map ◦

    https://github.com/rggen/rggen-systemverilog ◦ https://github.com/rggen/rggen-markdown ◦ https://github.com/rggen/rggen-sample-testbench ◦ https://github.com/rggen/rggen-plugin-template ◦ https://github.com/rggen/rggen-sample-plugin • 資料 ◦ https://qiita.com/taichi-ishitani/items/5155b2928b7d85370ae6 ◦ https://qiita.com/taichi-ishitani/items/d89738b5376503c813d8 ◦ https://github.com/rggen/rggen/wiki 18
  18. 発表当日出た質問と回答(追記あり) • リードデータの MUX が重い回路になりそうだが、なにか対策はしているか? ◦ 特にに対策はしていない。合成ツール頑張ってね、の方針。 ◦ ただ、実業務でも使っているが、そこがクリティカルパスになることはなかった。 ◦

    リードデータを MUX する箇所は module 化されているので、クリティカルパスになるようなら、当該 module を手元で変更するのが良いと思う。 ▪ https://github.com/rggen/rggen-sv-rtl/blob/master/rggen_adapter_common.sv ▪ RgGen が生成する RTL には手を入れない。 20
  19. 発表当日出た質問と回答(追記あり) • CSR モジュールのサニティチェック的なテストはどの様なテストを生成するか? ◦ RgGen としては、特に出力はしない。 ◦ UVM に

    CSR 用のテストシーケンスがあるので、それで代用するつもり。 ◦ RgGen では、テストシーケンスを実行できるようにするための、 UVM RAL モデルを出力する。 ◦ https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.2/html/index. html の “Register Layer” を参照 21
  20. 発表当日出た質問と回答(追記あり) • 生成した RTL に不整合が無いことは保証されているか? ◦ レジスタマップ読み込み時に不整合がないことを確認はしているが、保証はしない。 ◦ 生成物に対しても然り。 ◦

    OSS、かつ、趣味の産物なので、「使用者の責任において、生成物を使ってね」の方針。 ◦ CSR 関連のファイルのコーディングの手間を減らす、仕様と実装の乖離を防ぐのが目的のツール であって、全てを自動化するツールではない。 ◦ RgGen の実装もユニットテストも全て公開しているので、気になるなら、自身で確認してほしいし、 自身が満足のいく検証用論理を実装して、 PR を出してほしい。 23
  21. 実装しているエラーチェック • レジスタマップ読み込み時に、いくつかのエラーチェックを行って、レジスタマップに 不整合がないか確認しています ◦ 保証はしません ◦ 検証をするなど、使用者の責任において、生成物を使ってください • レジスタマップの実装は以下のリポジトリにあります

    ◦ https://github.com/rggen/rggen-default-register-map ◦ チェックの実装を見たい場合、 lib の下で verify を検索してください ◦ https://github.com/rggen/rggen-default-register-map/blob/a7ecd4c68824a9f7b51c5231d16657 636befdaca/lib/rggen/default_register_map/bit_field/bit_assignment.rb#L51 24
  22. 実装しているエラーチェック(レジスタブロック) • レジスタ名がレジスタブロック内で重複がないか • オフセットアドレスは 0 以上か • オフセットアドレスはデータ幅の倍数になっているか •

    オフセットアドレスがレジスタブロック内で重複がないか ◦ レジスタ全体のアクセス属性が read only と write only であれば、アドレス領域の重複を許容して いる • あるレジスタが占めるアドレス領域が、レジスタブロックの byte_size の範囲内か ◦ offset_address + register_width * size • size の指定は正数になっているか 26
  23. 実装しているエラーチェック(レジスタブロック) • 間接参照レジスタのチェック項目 ◦ 別々のレジスタが同じアドレス領域を共有する場合、間接参照用のビットフィールドで区別できるよ うになっているか ▪ 同じビットフィールドで、参照する際の値が異なるものが含まれていること ▪ foo_bit_field:

    0 と foo_bit_field: 1 は区別可能で、これが 1つ以上含まれていること ◦ 配列のインデックスを指すビットフィールドの個数と、配列の次元が同じになっているか ◦ 参照する際の値 (配列のインデックス、指定された値 )がビット幅の範囲に収まっていること ◦ 自身の配下のビットフィールドを参照用ビットフィールドに指定していない事 ◦ 参照ビットフィールドは、配列レジスタ配下ではなく、かつ、繰り返しビットフィールドになっていない こと 27
  24. 実装しているエラーチェック(ビットフィールド) • ビットフィールド名がレジスタ内で重複していないこと • ビット配置に重複がないこと ◦ (既存のビットフィールドの配置 ) & (自身の配置)

    が 0 になること • 初期値がビット幅に範囲に収まっていること • 初期値が配列状になっている場合、初期値の配列の大きさと、ビットフィールドの繰 り返し数が同じであること • 初期値の指定が必須のビットフィールドで、初期値の指定があること 28
  25. 実装しているエラーチェック(ビットフィールド) • 参照ビットフィールドのチェック ◦ 存在して、予約済みでないか ◦ 参照ビットフィールドのビット幅が、参照元が指定する値以上になっているか ◦ 配列レジスタ配下のビットフィールドを参照している場合 ▪

    自身も配列レジスタ配下のビットフィールドか ▪ 参照先の配列レジスタの大きさと、自身の配列の大きさが同じであること ◦ 繰り返しビットフィールドを参照している場合 ▪ 自身も繰り返しビットフィールドになっているか ▪ 参照先の繰り返し数と自身の繰り返し数が同じであること 29