FPGA開発日記

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

32ビット以上のメモリアクセスをどのようにしてISSでシミュレートするか検討

RISC-VのISSで、MMUの実装を検討している。その中で、MMUのテーブルサイズは64ビットとして定義されているが、これまでは、これを32ビットアクセスの2回として実現していた。 しかし、やはり実際には、64ビットアクセスは一度のアクセスとして実現したい。というか、ISSとしては最終的に8ビット(1バイトのアクセス)に落とし込んでいるのだから、64ビット、128ビットのメモリアクセスもシームレスに拡張できるはずだ。これをやっていこう。

このような対応をしておけば、今後より大きなSIMD命令でのメモリアクセスも、同様に実現できるはずだ。

1. 32ビットよりも大きな値を引数として取り出す

たとえば、メモリフェッチは、これまでは32ビットの変数のポインタを渡していた。

/*!
 * Load Data from Memory
 * it is different from LoadMemory, FetchMemory doesn't recorded to trace
 */
MemResult EnvBase::FetchMemory (Addr_t addr, Word_t *data)
{
  Byte_t byte_data[4];
  MemResult result = m_memory->LoadMemWord (ConvertVirtualAddress (addr), data);
  return result;
}

これを、基本的に関数のプロトコルとして、バイトサイズの配列として並べといて、引数としてサイズ情報を渡すようにする。

/*!
 * Load Data from Memory
 * it is different from LoadMemory, FetchMemory doesn't recorded to trace
 */
MemResult EnvBase::FetchMemory (Addr_t addr, Word_t *data)
{
  Byte_t byte_data[4];
  MemResult result = m_memory->LoadMemWord (ConvertVirtualAddress (addr), byte_data);
  memcpy (data, byte_data, 4);
  return result;
}

あるいは、

MemResult EnvBase::LoadMemory (Addr_t addr, Size_t size, Byte_t *data)
{
  MemResult res;
  Word_t record_data;

  switch (size) {
  case Size_Byte: {
    res = LoadMemByte  (addr, data);
    break;
  }
  case Size_HWord: {
    res = LoadMemHWord (addr, data);
    break;
  }
  case Size_Word:
    res = LoadMemWord (addr, data);
    break;
  default:
    fprintf (m_dbgfp, "<Internal Error: Illegal size of LoadMemory : %d>\n", size);
    exit (EXIT_FAILURE);
    break;
  }

  record_data = static_cast<Word_t>(*data);
  m_trace->RecordTraceMemRead (addr, record_data, size);

常にメモリアクセスの単位は統一しておき、あとはサイズ情報だけで何バイト渡すかを決めるという方法が良いだろう。

2. 現状、まだ動作していないところが多い

かなりAPIの部分を変えたため、まだちゃんと動作していない。ctestでは大デグレード状態だ。 頑張って修正する。