FPGA開発日記

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

Chisel+Diplomacyの構成で自作CPUからの命令フェッチを確認

Chiselを使ったDiplomacyのデザイン作成、ELFファイルのメモリへのロードパスは完成したので、CPUからフェッチを実行してみる。

CPUはメモリロード中はリセットしており、これを解除するためのシーケンスを作成する。特定のメモリアドレスにアクセスするとCPUをリセットするようにした。しかしこれもダサいのでなんとかしたいなあ。

      case 1 : {
        *debug_req_valid     = 1;
        *debug_req_bits_addr = 0x20000000;
        *debug_req_bits_data = 1;

        state = 2;

Chisel側の実装は以下。

  lazy val module = new LazyModuleImp(this) {
    val io = IO(new Bundle {
      val req   = Input(Bool())
      val addr  = Input(UInt(32.W))
      val data  = Input(UInt(32.W))
      val ready = Output(Bool())
    })

    loader.module.io.req  := io.req && (io.addr =/= 0x20000000.U)
    loader.module.io.addr := io.addr
    loader.module.io.data := io.data
    io.ready := loader.module.io.ready

    // CPU Core Contorl
    val cpu_run = RegInit(false.B)
    cpu_run := Mux(io.req && (io.addr === 0x20000000.U), io.data(0), cpu_run)
    core.module.io.run := cpu_run

CPU側のフェッチ動作を確認する。メモリから命令をフェッチして正しく実行できるようだ。最初のジャンプに対応してフェッチ先の命令が変わっている。

f:id:msyksphinz:20201128020006p:plain

このプログラムは最終的にメモリに値をストアして終了なので、TileLinkのDチャネルからデータを書き込んでいればよろしい。この動作は正しく動いているようだ。

f:id:msyksphinz:20201128020022p:plain

CPUの数を増やしてみる

試しにCPUの数を2つに増やして、ちゃんとフェッチ動作できるか見てみた。

  val core0   = LazyModule(new CoreTop("core0"))
  val core1   = LazyModule(new CoreTop("core1"))
  val xbar   = LazyModule(new TLXbar)
  val memory = LazyModule(new TLRAM(AddressSet(0x80000000L, 0x0fff), beatBytes = ramBeatBytes))

  xbar.node := loader.node
  xbar.node := /* TLDelayer(0.0001) := */ core0.inst_node
  xbar.node := /* TLDelayer(0.0001) := */ core0.data_node
  xbar.node := core1.inst_node
  xbar.node := core1.data_node

結果は上手く行っていない。というか、XBarの所でどちらかのReady信号が落ちてしまうのは当然で、CPUのFetcherをReady信号に対応させないとどうしようもない。この辺も実装していこう。

f:id:msyksphinz:20201128020041p:plain