FPGA開発日記

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

TileLinkのCache Coherencyプロトコル (6. DualCore環境でのメモリを取り合うプログラムを試す)

msyksphinz.hatenablog.com

前回のコードは、ブートローダの動きを観察するにCRTに多少の改造を加えなければならないことが分かった。

  • crt.S
  # get core id
  csrr a0, mhartid
  # 最大4コアまでを仮定する
  li a1, 4
1:bgeu a0, a1, 1b

main()関数の中の動きは基本的に同じだが、各コアをシンクロするためにカウンタを持っておき、すべてのコアがアトミックに値を更新し終えるまで待ち合わせるような原始的な同期方法を取っている。

volatile int init_wait = 0;

int main (int hartid)
{
  if (hartid == 0) {
    for (int i = 0; i < 16; i++) {
      false_share_data.core_data[i] = 0;
    }
  }

  __asm__ __volatile__ ("amoadd.w x0, %0, (%1)": :"r"(1), "r"(&init_wait));

  while(init_wait != 2);

  slave_main(hartid);
}

全てのデータのアップデートを終えると、終了条件を確認するために、もう一度同期して終了する。

volatile int finish_wait = 0;

void slave_main(int hartid)
{
  printf ("hartid = %d\n", hartid);
  for (int i = 0; i < 100; i++) {
    false_share_data.core_data[hartid]++;
  }
  printf("core_data[%d] = %d\n", hartid, false_share_data.core_data[hartid]);

  __asm__ __volatile__ ("amoadd.w x0, %0, (%1)": :"r"(1), "r"(&finish_wait));

  while(finish_wait != 2);
}

これでRTLをシミュレーションして動作を確認してみる。

./simulator-chipyard-DualMediumBoomConfig-debug --vcd=false_sharing.dual.vcd --verbose \
    ../../software/test/false_sharing/main.riscv 2>&1 | spike-dasm | tee false_sharing.dual.log
$ spike-dasm < false_sharing.dual.log | grep -v ^1  | grep -v ^0
using random seed 1622289306
This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.
Listening on port 61167
hartid = 0
core_data[0] = 100
core_data[1] = 100
*** PASSED *** Completed after 75563 cycles
[UART] UART0 is here (stdin/stdout).

とりあえず2コアで動作するようになった。よしよし。次はL2エントリの取り合いを波形で確認してみる。