11#include <stdio.h>
2+ #include <string.h>
23
34#include "common.h"
45#include "device.h"
@@ -180,6 +181,11 @@ static inline uint32_t read_rs2(const hart_t *vm, uint32_t insn)
180181 return vm -> x_regs [decode_rs2 (insn )];
181182}
182183
184+ static inline void ic_invalidate_all (hart_t * vm )
185+ {
186+ memset (& vm -> ic , 0 , sizeof (vm -> ic ));
187+ }
188+
183189/* virtual addressing */
184190
185191void mmu_invalidate (hart_t * vm )
@@ -188,6 +194,7 @@ void mmu_invalidate(hart_t *vm)
188194 vm -> cache_load [0 ].n_pages = 0xFFFFFFFF ;
189195 vm -> cache_load [1 ].n_pages = 0xFFFFFFFF ;
190196 vm -> cache_store .n_pages = 0xFFFFFFFF ;
197+ ic_invalidate_all (vm );
191198}
192199
193200/* Pre-verify the root page table to minimize page table access during
@@ -301,11 +308,27 @@ static void mmu_fence(hart_t *vm, uint32_t insn UNUSED)
301308
302309static void mmu_fetch (hart_t * vm , uint32_t addr , uint32_t * value )
303310{
304- uint32_t vpn = addr >> RV_PAGE_SHIFT ;
305- if (unlikely (vpn != vm -> cache_fetch .n_pages )) {
311+ /* cache hit */
312+ uint32_t idx = (addr >> IC_SHIFT ) & IC_INDEX_MASK ;
313+ uint32_t tag = addr >> (IC_SHIFT + IC_INDEX_BITS );
314+ ic_block_t * blk = & vm -> ic .block [idx ];
315+
316+ if (likely (blk -> valid && blk -> tag == tag )) {
306317#ifdef MMU_CACHE_STATS
307- vm -> cache_fetch .misses ++ ;
318+ vm -> cache_fetch .hits ++ ;
308319#endif
320+ uint32_t ofs = addr & IC_BLOCK_MASK ;
321+ * value = * (const uint32_t * ) (blk -> base + ofs );
322+ return ;
323+ }
324+
325+ #ifdef MMU_CACHE_STATS
326+ vm -> cache_fetch .misses ++ ;
327+ #endif
328+
329+ /* cache miss, Continue using the original va->pa*/
330+ uint32_t vpn = addr >> RV_PAGE_SHIFT ;
331+ if (unlikely (vpn != vm -> cache_fetch .n_pages )) {
309332 mmu_translate (vm , & addr , (1 << 3 ), (1 << 6 ), false, RV_EXC_FETCH_FAULT ,
310333 RV_EXC_FETCH_PFAULT );
311334 if (vm -> error )
@@ -317,12 +340,14 @@ static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
317340 vm -> cache_fetch .n_pages = vpn ;
318341 vm -> cache_fetch .page_addr = page_addr ;
319342 }
320- #ifdef MMU_CACHE_STATS
321- else {
322- vm -> cache_fetch .hits ++ ;
323- }
324- #endif
343+
325344 * value = vm -> cache_fetch .page_addr [(addr >> 2 ) & MASK (RV_PAGE_SHIFT - 2 )];
345+
346+ /* fill into the cache */
347+ uint32_t block_off = (addr & RV_PAGE_MASK ) & ~IC_BLOCK_MASK ;
348+ blk -> base = (const uint8_t * ) vm -> cache_fetch .page_addr + block_off ;
349+ blk -> tag = addr >> (IC_SHIFT + IC_INDEX_BITS );
350+ blk -> valid = true;
326351}
327352
328353static void mmu_load (hart_t * vm ,
0 commit comments