FPGA開発日記

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

Chiselを使ってCPUを作ろう(12. テスト終了コードの取り扱いについて)

f:id:msyksphinz:20181123005953p:plain

Chiselを使って、非常にシンプルなCPUを作ってみるプロジェクト。RISC-Vにはfromhostやtohostといったレジスタ(メモリマップドレジスタ)が定義されており、それを使用してシミュレーションの制御を行う。

このメモリマップドレジスタはだいたい0x1000あたりに定義されており、そこにストアした値が0であればPassでテスト終了、などといった条件でPass / Failを判定する。

テストパタンの終了条件は、Scalaのテストベンチ側に以下のように記述することで実現した。

import util.control.Breaks._
...
  breakable {
    for (cycle <- 0 to 512) {
      val inst_valid = peek(cpu_tb.io.dbg_monitor.inst_valid)
      if (inst_valid == 1) {
        writer.printf("%10d : ".format(cycle))
        val reg_wren   = peek(cpu_tb.io.dbg_monitor.reg_wren)
        val reg_wraddr : Long = peek(cpu_tb.io.dbg_monitor.reg_wraddr).toLong
        val reg_wrdata : Long = peek(cpu_tb.io.dbg_monitor.reg_wrdata).toLong
...
        if (data_bus_req == 1 && data_bus_cmd == peek(CMD_WR) &&
            data_bus_addr == 0x1000) {
           if (data_bus_wrdata == 0x1) {
             writer.printf(" PASS : Simulation Finished\n")
           } else {
             writer.printf(" FAIL : Simulation Finished\n")
           }
           break
        }
      }

ScalaにはどうやらデフォルトでBreakが無いらしく、util.control.Breaksをインポートしてbreakしたいループをbreakableで囲むらしい。

私の環境では、パイプライントレーサがメモリアクセスを監視しているので、CMD_WRが出力され、かつ data_bus_addr == 0x1000 であるときは終了条件であるとし、ストアデータが0x1であればPass、それ以外であればFailとしてテストパタンを終了させることにした。

実行結果は以下となる。

make cpu_run && spike-dasm < pipetrace.log > pipetrace.dasm.log
  • pipetrace.dasm.log
       489 : x00<=0x0000000000000000 (15, 0000000000000000, 0000000000000000)                                : 0x0000060c : INST(0x00000073) : ecall
       490 : x00<=0x0000000000000000 (21, 0000000000000000, 0000000000000000)                                : 0x00000610 : INST(0xc0001073) : csrw    cycle, zero
       491 : x30<=0x0000000000000008 (21, 0000000000000000, 0000000000000008)                                : 0x00000004 : INST(0x34202f73) : csrr    t5, mcause
       492 : x31<=0x0000000000000008 ( 1, 0000000000000000, 0000000000000008)                                : 0x00000008 : INST(0x00800f93) : li      t6, 8
       493 :                                                                                                 : 0x0000000c : INST(0x03ff0a63) : beq     t5, t6, pc + 52
       495 : x30<=0x0000000000001040 ( 1, 0000000000001000, 0000000000000040)                                : 0x00000040 : INST(0x00001f17) : auipc   t5, 0x1
       496 :                                                                  [00001000]<=0x0000000000000001 : 0x00000044 : INST(0xfc3f2023) : sw      gp, -64(t5)
 PASS : Simulation Finished

無事にテストパタンがPassして、終了することが確認できた。