FPGA開発日記

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

自作RISC-Vコア向け環境のlibelfを置き換える試行

ひょんな理由でM1 Macを使う必要が生じたのだが、MacOSにはlibelfが無いということが分かった。 いろいろ考えて、x86Linux仮想マシンでシミュレートするか、それともそもそもMac環境で開発することを諦めるか考えたのだが、よく考えてみるとriscv-isa-sim(spike)はちゃんと動作している。どうしているんだろうと思ったら、libelfによるelfのローディングを使用せず、自前でelfを取り込む環境を用意していた。

github.com

elf.hは自前で定義しており、必要最低限の実装を用意しているようだ。memifにELFのデータを書いているようなので、これを現在使用しているELFローダの実装で置き換える。

github.com

このへんの実装だな。

#define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t, bswap)                         \
  do {                                                                         \
    ehdr_t* eh = (ehdr_t*)buf;                                                 \
    phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff));                          \
    *entry = bswap(eh->e_entry);                                               \
    assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum) * sizeof(*ph));     \
    for (unsigned i = 0; i < bswap(eh->e_phnum); i++) {                        \
      if (bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) {            \
        if (bswap(ph[i].p_filesz)) {                                           \
          assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz));       \
          memif->write(bswap(ph[i].p_paddr), bswap(ph[i].p_filesz),            \
                       (uint8_t*)buf + bswap(ph[i].p_offset));                 \
        }                                                                      \
        if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) {       \
          zeros.resize(pad);                                                   \
          memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), pad,      \
                       zeros.data());                                          \
        }                                                                      \
      }                                                                        \
    }                                                                          \

無理やり書き換える。下記のg_memoryに挿入したデータが、そのまま外部RAMに書き込まれてフェッチ・データアクセスに使用される。

  #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t, bswap) do { \
    ehdr_t* eh = (ehdr_t*)buf; \
    phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \
    /* *entry = bswap(eh->e_entry); */ \
    assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum)*sizeof(*ph)); \
    for (unsigned i = 0; i < bswap(eh->e_phnum); i++) {           \
      if(bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \
        if (bswap(ph[i].p_filesz)) {                  \
          assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \
          for (int b_idx = 0; b_idx < ph[i].p_filesz; b_idx++) { \
            g_memory->StoreMemory<Byte_t> (ph[i].p_paddr + b_idx, (Byte_t *)(buf + bswap(ph[i].p_offset) + b_idx)); \
          } \
        } \
        zeros.resize(bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)); \
      } \
    } \

一応ここまでで、シミュレーション環境を構築できるようになった。