FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

TileLinkの勉強 (5. Diplomacyがサポートするウィジェットについて(2))

前回の続き。

Chipyardのリファレンスは比較的詳しく書いてあると思うので、この資料を読みながらDiplomacyの勉強をしていこうと思う。

chipyard.readthedocs.io

今回はDiplomacyがサポートするウィジェットについて。AXI4とTileLinkについて様々なウィジェットがサポートされており、これらの部品を組み合わせることで任意のバスを構成していくことになる。

TLWidthWidget

TileLinkの物理的なインタフェースビット幅を変更する。TileLinkインタフェースのビット幅はマネージャにより構成されるが、クライアント側が特定のビット幅を持っていたい場合がある。

引数:

  • innerBeatBytes: Int - クライアント側から見た物理的なビット幅(バイト単位)

使用例:

// マネージャノードがbeatBytesを8に設定している。
// WidthWidgetにより、クライアントはbeatByetsが4に設定されている。
manager.node := TLWidthWidget(4) := client.node

TLFIFOFixer

FIFOドメインを宣言したTileLinkマネージャは、クライアントから到達する、そのドメインへのすべてのFIFOオーダリングなリクエストがリクエストの順番通りに返されることを保証しなければならない。しかし、そのレスポンスの順序を制御するだけでは、同じFIFOドメイン内の他のマネージャからのインタリーブされたレスポンスを制御することができない。FIFOの順序を保証するための責任はTLFIFOFixerにより達成される。

引数:

  • policy: TLFIFOFixer.Policy - (オプション) どのマネージャがTLFIFOFixerにオーダリングを行わせるか?(デフォルト: TLFIFOFixer.all)

policyが取ることのできる引数は以下のとおりである。

  • TLFIFOFixer.all - すべてのマネージャ(FIFOドメイン以外のマネージャも含む)のオーダリングが保証される。
  • TLFIFOFixer.allFIFO - All managers that define a FIFO domain will have ordering guaranteed
  • TLFIFOFixer.allFIFO - FIFOドメインを定義するすべてのマネージャがオーダリングを保証される。
  • TLFIFOFixer.allVolatile - VOLATILE, PUT_EFFECTS, GET_EFFECTSのリージョンタイプを持つすべてのマネージャがオーダリングを保証させる(リージョンタイプについてはManager Nodeを参照すること)。

TLXbar と AXI4Xbar

TileLinkおよびAXI4のクロスバージェネレータであり、TL/AXIクライアントからのリクエストを、マネージャ・スレーブのアドレス定義に基づいてTL/AXIのスレーブに転送する。通常はこのウィジェットは引数無しで生成される。しかし、アービタ内でどのクライアントポートが優先権を手に入れるかなどのアービトレーションのポリシーを変更することができる。デフォルトのポリシーはTLArbiter.roundRobinであるが、優先権洗濯ポリシーを変更したい場合はTLArbiter.lowestIndexFirstに変更することができる。

引数:

All arguments are optional.

すべての引数はオプションである。

  • arbitrationPolicy: TLArbiter.Policy - 使用するアービトレーションのポリシー
  • maxFlightPerId: Int - (AXI4のみ) 同じIDにおいて同時にインフライトになれるIDの数(デフォルト: 7)。
  • awQueueDepth: Int - (AXI4のみ) ライトアドレスキューのサイズ(デフォルト: 2)

使用例:

// lazyモジュールでクロスバーをインスタンス化する。
val tlBus = LazyModule(new TLXbar)

// 単一の入力エッジの接続。
tlBus.node := tlClient0.node
// 複数の入力エッジの接続。
tlBus.node :=* tlClient1.node

// 単一の出力エッジの接続。
tlManager0.node := tlBus.node
// 複数の出力エッジの接続。
tlManager1.node :*= tlBus.node

// クロスバーをlowestIndexFirstのアービトレーションポリシーで宣言する。
// TLArbiterのsingletonを使用しているが、実際にはAXI4である。
val axiBus = LazyModule(new AXI4Xbar(TLArbiter.lowestIndexFirst))

// TLと同様に接続される。
axiBus.node := axiClient0.node
axiBus.node :=* axiClient1.node
axiManager0.node := axiBus.node
axiManager1.node :*= axiBus.node

TLToAXI4 と AXI4ToTL

TileLinkとAXI4プロトコルのコンバータである。TLToAXI4はクライアントにTileLinkを持ち、AXI4スレーブに接続する。AXI4ToTLはAXI4マスターをTileLinkのマネージャに接続する。通常はデフォルトの引数をオーバライドすることはない。

使用例:

axi4slave.node :=
    AXI4UserYanker() :=
    AXI4Deinterleaver(64) :=
    TLToAXI4() :=
    tlclient.node

tlmanager.node :=
    AXI4ToTL() :=
    AXI4UserYanker() :=
    AXI4Fragmenter() :=
    axi4master.node

TLToAXI4コンバータの後には、AXI4Deinterleaver を挿入する必要がある。なぜなら、TLToAXI4コンバータはインタリーブされたリードレスポンスを取り扱うことができないからだ。TLToAXI4コンバータはAXI4のユーザフィールドを使用していくつかの情報を格納する。したがってユーザフィールドの存在しないAXI4ポートに接続する場合にはAXI4UserYankerを接続する必要がある。

AXI4ポートをAXI4ToTLウィジェットに接続する場合、AXI4FragmenterAXI4UserYankerを接続する必要がある。なぜならば、コンバータはユーザフィールドおよび複数ビートのトランザクションを扱うことができないからである。

TLROM

The TLROM widget provides a read-only memory that can be accessed using TileLink. Note: this widget is in the freechips.rocketchip.devices.tilelink package, not the freechips.rocketchip.tilelink package like the others.

TLROMウィジェットはTileLink経由でアクセスすることのできるRead-Onlyのメモリである。このウィジェットfreechips.rocketchip.devices.tilelinkパッケージに含まれており、freechips.rocketchip.tilelinkではないことに注意が必要である。

引数:

  • base: BigInt - メモリのベースアドレス
  • size: Int - バイト単位でのメモリサイズ
  • contentsDelayed: => Seq[Byte] - ROMのバイト内容を生成するための関数。
  • executable: Boolean - (オプション) CPUがこのROMの内容をフェッチすることができるかを示す(デフォルト: true)
  • beatBytes: Int - (オプション) バイト単位でのインタフェースのビット幅。(デフォルト: 4)
  • resources: Seq[Resource] - (オプション) デバイスツリーに接続されるリソースのシーケンス

使用例:

val rom = LazyModule(new TLROM(
  base = 0x100A0000,
  size = 64,
  contentsDelayed = Seq.tabulate(64) { i => i.toByte },
  beatBytes = 8))
rom.node := TLFragmenter(8, 64) := client.node

サポートされる操作:

TLROMは単一ビートの読み込みのみサポートされる。複数ビートの読み込みを行う場合、TLFragmenterをROMの前に配置する必要がある。

TLRAM と AXI4RAM

The TLRAM and AXI4RAM widgets provide read-write memories implemented as SRAMs.

TLRAMとAXI4RAMウィジェットSRAMとして実装されるRead-Writeメモリである。

引数:

  • address: AddressSet - RAMがカバーするアドレス範囲。
  • cacheable: Boolean - (オプション) RAMのコンテンツをキャッシュできるかを示す(デフォルト: true)。
  • executable: Boolean - (オプション) RAMのコンテンツが命令としてフェッチできるかを示す(デフォルト: true)
  • beatBytes: Int - (オプション) TL/AXI4インタフェースの幅をバイト単位で示す(デフォルト: 4)。
  • atomics: Boolean - (オプション, TileLinkのみ) RAMがアトミック操作をサポートするかを示す(デフォルト: false)。

使用例:

val xbar = LazyModule(new TLXbar)

val tlram = LazyModule(new TLRAM(
  address = AddressSet(0x1000, 0xfff)))

val axiram = LazyModule(new AXI4RAM(
  address = AddressSet(0x2000, 0xfff)))

tlram.node := xbar.node
axiram := TLToAXI4() := xbar.node

サポートされている操作:

TLRAMはTL-ULリクエストの単一ビートのみをサポートしている。atomicsをtrueに設定すると、LogicalとArithmeticの操作をサポートする。複数ビートのRead/Writeを行いたい場合はTLFragmenterを接続すること。

AXI4RAMはAXI4-Liteの操作のみをサポートするため、複数ビートのRead/Writeおよび最大サイズよりも小さなRead/Writeはサポートされない。フルのAXI4プロトコルを使用したい場合は AXI4Fragmenterを使用すること。