いまいち実装が進んでいないが、Sv32とSv39のISSへの実装しなおしが完了した。
Sv32とSv39については、前回の記事を参考にして欲しい。
実装方法としては、まずはPTEを参照しながら上位の物理アドレスを生成していき、最後にPTEを参照しないアドレスを付加する。
for (level = init_level-1; level >= 0; level--) { bool is_leaf_achieve = false; Byte_t p_pte[4] = {0}; Addr_t va_vpn_i = static_cast<UWord_t>(vaddr) >> (12 + 10 * level) & 0x3ff; pte_addr += va_vpn_i * PTESIZE; pte_addr = ExtendSign(pte_addr, 31); LoadMemoryDebug (pte_addr, Size_Word, p_pte); memcpy (&pte_val, p_pte, 4); ... Addr_t mask = ((pte_val >> pte_idx[level]) & ((1 << pte_len[level])-1)) << ppn_idx[level]; phy_addr |= ((pte_val >> pte_idx[level]) & ((1 << pte_len[level])-1)) << ppn_idx[level]; pte_addr = ((pte_val >> pte_len[0]) & ((1 << (31-pte_len[0]+1))-1)) * PAGESIZE; // str << std::hex << " <Temporary Mask = " << std::hex << mask << ">\n"; // str << std::hex << " <Temporary PhyAddr = " << std::hex << std::setw(16) << std::setfill('0') << phy_addr << ">\n"; // DebugPrint ("%s", str.str().c_str()); if (is_leaf_achieve) break; } // 下位のアドレスを接続する。 for (level = level-1; level >= 0; level--) { phy_addr |= (vaddr >> vpn_idx[level]) & ((1 << vpn_len[level])-1) << ppn_idx[level]; }
これで実装をしてみたのだが、テストパタンとしては途中でテーブル参照エラーを起こし、最後は無限ループになってしまった。結局最大サイクル数で停止してしまう。spikeでも同様のようだ。 これで本当にテストパタンはあっているのだろうか?