FPGA開発日記

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

Parameter / Conifgで作るコンフィグレーション可能なChiselデザイン

Chiselのアドバンスドな使い方はDiplomacy / Parameters / Configあたりを使いこなすことだと言われる。ParametersとConfigについては何となく理解しているつもりだが具体的なサンプルを使って確かめていなかったのでいくつか調査している。

最もシンプルな例はおそらくRISCV-Miniによる実装だろう。

https://github.com/ucb-bar/riscv-mini

  • src/main/scala/Config.scala
class MiniConfig extends Config((site, here, up) => {
    // Core
    case XLEN => 32
    case Trace => true
    case BuildALU    => (p: Parameters) => Module(new ALUArea()(p))
    case BuildImmGen => (p: Parameters) => Module(new ImmGenWire()(p))
    case BuildBrCond => (p: Parameters) => Module(new BrCondArea()(p))
    // Cache
    case NWays => 1 // TODO: set-associative
    case NSets => 256 
    case CacheBlockBytes => 4 * (here(XLEN) >> 3) // 4 x 32 bits = 16B
    // NastiIO
    case NastiKey => new NastiParameters(
      idBits   = 5,
      dataBits = 64,
      addrBits = here(XLEN))
  }
)

複数のパラメータがここで定義されている。これはConfigクラスを継承したもので、Configクラス自体はRocket-Chipに実装されている機能である(注意なのだがDiplomacyも含め、ConfigやParameterと言った機能はChiselやScalaそのものの機能ではなく、Scala上で構成されているプログラムに過ぎない)

これをモジュールのインスタンス化する際に渡してやることでモジュール内でこれらのパラメータを参照できるようになる。例えばRISCV-Miniでは以下のようにしてこのパラメータをモジュールに適用している。

  • src/main/scala/Main.scala
object Main extends App {
  val dir = new File(args(0)) ; dir.mkdirs
  // Configuration MiniConfigをインスタンス化してTileにパラメータとして渡している
  val params = (new MiniConfig).toInstance
  val chirrtl = firrtl.Parser.parse(chisel3.Driver.emit(() => new Tile(params)))
  val writer = new FileWriter(new File(dir, s"${chirrtl.main}.fir"))
  writer write chirrtl.serialize
  writer.close

これはTileモジュールからはtileParams: Parametersとして見えるようになる。さらに省略してpという文字で参照できるようにしてある。

class Tile(tileParams: Parameters) extends Module with TileBase {
  implicit val p = tileParams

これらのパラメータは暗黙的なパラメータとして各モジュールに伝搬される。

class HostIO(implicit p: Parameters) extends CoreBundle()(p) {
  val fromhost = Flipped(Valid(UInt(xlen.W)))
  val tohost   = Output(UInt(xlen.W))
}

class CoreIO(implicit p: Parameters) extends CoreBundle()(p) {
  val host = new HostIO
  val icache = Flipped((new CacheIO))
  val dcache = Flipped((new CacheIO))
}

これを応用して、自作のDiplomacyジェネレータにParameterを追加してみた。以下のような新たなConfigを作成してみる。

import freechips.rocketchip.config._

class Bus128BitConfig extends Config((site, here, up) => {
  case BusWidthBytes => 128 / 8
})

そして、このConfigをインスタンス化して実装モジュールに適用させてみた。

object Generator {
    final def main(args: Array[String]) {
        val p = (new Bus64BitConfig).toInstance
        val verilog = Driver.emitVerilog(
            new TestHarness()(p)
        )
    }
}

Bus128BitConfig内で定義したBusWidthBytesは、以下のSoCモジュール内でパラメータとして使用している。p(BusWidthBytes)として参照可能になっている。

class core_complex(txns: Int)(implicit p: Parameters) extends LazyModule {
  val pusher1 = 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 ifu    = LazyModule(new ifu("ifu"))

  val xbar   = LazyModule(new TLXbar)
  // p(BusWidthBytes)でバスの幅を決めている
  val memory = LazyModule(new TLRAM(AddressSet(0x02000, 0x0fff), beatBytes = p(BusWidthBytes)))

  xbar.node := pusher1.node
    ...

これで生成したVerilogを確認してみると、無事にバス幅を128ビットに変更できていた。

module TLRAM(
  input          clock,
  input          reset,
  output         auto_in_a_ready,
  input          auto_in_a_valid,
  input  [2:0]   auto_in_a_bits_opcode,
  input  [2:0]   auto_in_a_bits_param,
  input  [2:0]   auto_in_a_bits_size,
  input          auto_in_a_bits_source,
  input  [13:0]  auto_in_a_bits_address,
  input  [15:0]  auto_in_a_bits_mask,
  input  [127:0] auto_in_a_bits_data,
  input          auto_in_a_bits_corrupt,
  input          auto_in_d_ready,
  output         auto_in_d_valid,
  output [2:0]   auto_in_d_bits_opcode,
  output [2:0]   auto_in_d_bits_size,
  output         auto_in_d_bits_source,
  output [127:0] auto_in_d_bits_data
);
    ....

f:id:msyksphinz:20201007152925p:plain