FPGA開発日記

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

TileLinkのDiplomacyを使った実際のデザインを試してみる (7. TLXbarによる複数のスレーブを使ったデザイン)

次に作るのは、TLXbarを使って2つのスレーブを使ったデザインだ。2つのスレーブを接続することで、例えば2つのRAMを使ってスレーブに接続できるようになる。

ターゲット回路

例えば、以下のようなデザインを作成した。

class TLTwoRAM(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule {
  val pusher = LazyModule(new TLPatternPusher("pat1", Seq(
    new WritePattern(0x100, 0x2, 0x012345678L),
    new WritePattern(0x500, 0x2, 0x0abcdef01L),
    new ReadExpectPattern(0x100, 0x2, 0x012345678L),
    new ReadExpectPattern(0x500, 0x2, 0x0abcdef01L)
  )))
  val model  = LazyModule(new TLRAMModel("SRAMSimple"))
  val xbar   = LazyModule(new TLXbar)
  val ram0   = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff), beatBytes = ramBeatBytes))
  val ram1   = LazyModule(new TLRAM(AddressSet(0x400, 0x3ff), beatBytes = ramBeatBytes))

  xbar.node := model.node := pusher.node
  ram0.node := xbar.node
  ram1.node := xbar.node

  lazy val module = new LazyModuleImp(this) with UnitTestModule {
    pusher.module.io.run := true.B
    io.finished := pusher.module.io.done
  }
}

これは、xbarを通じて1つのマスターに対して2つのスレーブを接続している。2つのRAMのアドレスマップを以下のように構成する。

  1. 0x000 - 0x3ff
  2. 0x400 - 0x7ff

この時のPatternPusherは以下のようにパタンを挿入する。

  • WritePattern : 0x100に対してサイズ22バイトの書き込み 0x12345678 を行う。
  • WritePattern : 0x500に対してサイズ22バイトの書き込み 0xabcdef01 を行う。
  • ReadExpectPattern : 0x100に対してサイズ22バイトの読み込み操作を行い、想定するデータは0x12345678である。
  • ReadExpectPattern : 0x500に対してサイズ22バイトの読み込み操作を行い、想定するデータは0xabcdef01である。

実行結果

波形を取った結果、以下のようになった。無事に2つのRAMにアクセスしていることが確認できる。

f:id:msyksphinz:20200104232631p:plain
複数スレーブでのRTLシミュレーション実行結果

TileLinkのノード関係図

ノード関係図は正常に作成されている。

f:id:msyksphinz:20200104232706p:plain
複数スレーブでのDiplomacyノードのGraphML出力結果

2マスター2スレーブのTileLinkバスを作成する

次に、複数マスター・複数スレーブの構成を作成してみる。

class TLManyMasterManySlave(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends LazyModule {
  val pusher0 = LazyModule(new TLPatternPusher("pat1", Seq(
    new WritePattern(0x100, 0x2, 0x012345678L),
    new WritePattern(0x500, 0x2, 0x0abcdef01L),
    new ReadExpectPattern(0x100, 0x2, 0x012345678L),
    new ReadExpectPattern(0x500, 0x2, 0x0abcdef01L)
  )))
  val pusher1 = LazyModule(new TLPatternPusher("pat1", Seq(
    new WritePattern(0x200, 0x2, 0x012345678L),
    new WritePattern(0x600, 0x2, 0x0abcdef01L),
    new ReadExpectPattern(0x200, 0x2, 0x012345678L),
    new ReadExpectPattern(0x600, 0x2, 0x0abcdef01L)
  )))
  val model0 = LazyModule(new TLRAMModel("SRAMSimple"))
  val model1 = LazyModule(new TLRAMModel("SRAMSimple"))
  val xbar   = LazyModule(new TLXbar)
  val ram0   = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff), beatBytes = ramBeatBytes))
  val ram1   = LazyModule(new TLRAM(AddressSet(0x400, 0x3ff), beatBytes = ramBeatBytes))

  xbar.node := model0.node := pusher0.node
  xbar.node := model1.node := pusher1.node
  ram0.node := xbar.node
  ram1.node := xbar.node

  lazy val module = new LazyModuleImp(this) with UnitTestModule {
    pusher0.module.io.run := true.B
    pusher1.module.io.run := true.B
    io.finished := pusher0.module.io.done && pusher1.module.io.done
  }
}

これでRTLシミュレーションを実行する。

f:id:msyksphinz:20200104232805p:plain
複数マスター・複数スレーブでのDiplamcy RTLシミュレーション実行結果
f:id:msyksphinz:20200104232843p:plain
複数マスター・複数スレーブでのDiplamcy GraphMLの出力結果