FPGA開発日記

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

ISSにL1キャシュのシミュレーション機能の検討(3. L1命令キャッシュのモデル実装とリファクタリング)

f:id:msyksphinz:20160520003556j:plain

前回までで、L1キャッシュのモデルをISSに実装したのだが、L1 データキャッシュのシミュレーションしか実装していなかった。

L1キャッシュへのアクセスは命令フェッチの際に発生する。しかも今度はL1データキャッシュと違ってストアは発生しない。この方が楽だ。

L1キャッシュへのアクセス制御を一つの関数としてまとめる

github.com

void RiscvEnv::UpdateL1Icache (Addr_t addr)
{
  if (FLAGS_sim_l1i) {
    Addr_t l1i_addr      = MaskL1IAddr (addr);
    Addr_t l1i_entry_idx = MaskL1IIndex (addr);
    if (!m_icache_en[l1i_entry_idx]) {   // L1I corresponding entry is empty
      m_icache_addr[l1i_entry_idx] = l1i_addr;
      m_icache_en  [l1i_entry_idx] = true;
      DebugPrint ("[L1I:E:%08x,%03d]            ", l1i_addr, l1i_entry_idx);
    } else {
      if (m_icache_addr[l1i_entry_idx] == l1i_addr) {  // L1I corresponding entry is HIT
        DebugPrint ("[L1I:H:%08x,%03d]            ", l1i_addr, l1i_entry_idx);
      } else {   // L1I corresponding entry is MISS
        DebugPrint ("[L1I:R:%08x-->%08x,%03d] ", m_icache_addr[l1i_entry_idx], l1i_addr, l1i_entry_idx);
        m_icache_addr[l1i_entry_idx] = l1i_addr;
      }
    }
  }
}


void RiscvEnv::UpdateL1Dcache (Addr_t addr)
{
  if (FLAGS_sim_l1d) {
    Addr_t l1d_addr      = MaskL1DAddr (addr);
    Addr_t l1d_entry_idx = MaskL1DIndex (addr);
    if (!m_dcache_en[l1d_entry_idx]) {   // L1D corresponding entry is empty
      m_dcache_addr[l1d_entry_idx] = l1d_addr;
      m_dcache_en  [l1d_entry_idx] = true;
      DebugPrint ("[L1D:E:%08x,%03d]\n", l1d_addr, l1d_entry_idx);
    } else {
      if (m_dcache_addr[l1d_entry_idx] == l1d_addr) {  // L1D corresponding entry is HIT
        DebugPrint ("[L1D:H:%08x,%03d]\n", l1d_addr, l1d_entry_idx);
      } else {   // L1D corresponding entry is MISS
        DebugPrint ("[L1D:R:%08x-->%08x,%03d]\n", m_dcache_addr[l1d_entry_idx], l1d_addr, l1d_entry_idx);
        m_dcache_addr[l1d_entry_idx] = l1d_addr;
      }
    }
  }
}

L1キャッシュの実装を追加した。命令フェッチの部分にICacheの実装を追加しておく。

MemResult EnvBase::FetchMemory (Addr_t addr, Word_t *data)
{
  Byte_t byte_data[4];
  Addr_t phy_pc = ConvertVirtualAddress (addr, MemAccType::FetchMemType);

  UpdateL1Icache (phy_pc);

  GetTrace()->SetTracePhyPC(phy_pc);
  MemResult result = m_memory->LoadMemWord (phy_pc, byte_data);
  memcpy (data, byte_data, 4);
  return result;
}

オプションとして--sim_l1d, --sim_l1iを用意しておく。--sim_l1iを追加することで、以下のようにログが追加される。

[L1I:E:00000000,032]                     0:M:MBar:[00000200][P00000200] 00008197 : auipc      r03,0x00008          r03<=00008200
[L1I:H:00000000,032]                     1:M:MBar:[00000204][P00000204] e1018193 : addi       r03,r03,0xe10        r03=>00008200 r03<=00008010
[L1I:H:00000000,032]                     2:M:MBar:[00000208][P00000208] 0000c117 : auipc      r02,0x0000c          r02<=0000c208
[L1I:H:00000000,032]                     3:M:MBar:[0000020c][P0000020c] e0010113 : addi       r02,r02,0xe00        r02=>0000c208 r02<=0000c008
[L1I:E:00000000,033]                     4:M:MBar:[00000210][P00000210] 000000b3 : add        r01,r00,r00          r00=>00000000 r00=>00000000 r01<=00000000
[L1I:H:00000000,033]                     5:M:MBar:[00000214][P00000214] 00000233 : add        r04,r00,r00          r00=>00000000 r00=>00000000 r04<=00000000
[L1I:H:00000000,033]                     6:M:MBar:[00000218][P00000218] 000002b3 : add        r05,r00,r00          r00=>00000000 r00=>00000000 r05<=00000000
[L1I:H:00000000,033]                     7:M:MBar:[0000021c][P0000021c] 00000333 : add        r06,r00,r00          r00=>00000000 r00=>00000000 r06<=00000000
...