FPGA開発日記

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

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

DualCoreでL2キャッシュの同じラインを取り合うようなプログラムを作ってみることにする。

試してみるのはFalse Sharingのテストで、同じキャッシュラインで別の場所に別のコアが値を書き込み続け、そのキャッシュラインを複数のコアが取り合うようなコードだ。

 #include <stdint.h>

 #define CSR_MHARTID (0xf14)

 #define read_csr(reg) ({ unsigned long __tmp; \
   asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
   __tmp; })


 volatile struct false_sharing_data_t {
   int32_t core_data[16] __attribute__((aligned(64)));
 } false_share_data;

 void slave_main(int hartid);

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

   slave_main(hartid);
 }

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

false_share_dataのラインを各コアがアップデートする(ただし書き込む場所はそれぞれのコアでことなるのでAtomic性を考える必要はない)。以下のようにしてコンパイルし、バイナリを作ってみることにする。

$ riscv64-unknown-elf-gcc -static -mcmodel=medany -fno-common -fno-builtin-printf -nostdlib -nostartfiles -lm \
    -lgcc -T link.ld syscalls.c crt.S main.c -o main.riscv

以下のようにしてChipyard上の2コア環境で動かしてみることにする。

$ ./simulator-chipyard-DualMediumBoomConfig-debug --vcd=false_sharing.dual.vcd \
    --verbose ../../software/test/false_sharing/main.riscv 2>&1 | tee false_sharing.dual.log

結果を確認してみる。あれ、1コア分しか動いてないなあ。。。?

$ grep -v DASM false_sharing.dual.log
using random seed 1622245092
This emulator compiled with JTAG Remote Bitbang client. To enable, use +jtag_rbb_enable=1.
Listening on port 53315
hartid = 0
*** PASSED *** Completed after 87700 cycles
[UART] UART0 is here (stdin/stdout).

ログ自体はコア番号が出力されないのでどのコアが何を実行しているのか良く分からない。ログ出力をちょっと変えてみよう。

diff --git a/src/main/scala/exu/core.scala b/src/main/scala/exu/core.scala
index 579fce89..6f89e067 100644
--- a/src/main/scala/exu/core.scala
+++ b/src/main/scala/exu/core.scala
@@ -1334,14 +1334,16 @@ class BoomCore(usingTrace: Boolean)(implicit p: Parameters) extends BoomModule
       // To allow for diffs against spike :/
       def printf_inst(uop: MicroOp) = {
         when (uop.is_rvc) {
-          printf("(0x%x)", uop.debug_inst(15,0))
+          printf("DASM(0x%x)", uop.debug_inst(15,0))
         } .otherwise {
-          printf("(0x%x)", uop.debug_inst)
+          printf("DASM(0x%x)", uop.debug_inst)
         }
       }

       when (rob.io.commit.arch_valids(w)) {
-        printf("%d 0x%x ",
+        printf("%d %d %d 0x%x ",
+          csr.io.hartid,
+          csr.io.time,
           priv,
           Sext(rob.io.commit.uops(w).debug_pc(vaddrBits-1,0), xLen))
         printf_inst(rob.io.commit.uops(w))