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 icache_invalidate_all (hart_t * vm )
185+ {
186+ memset (& vm -> icache , 0 , sizeof (vm -> icache ));
187+ }
188+
183189/* virtual addressing */
184190
185191void mmu_invalidate (hart_t * vm )
@@ -197,6 +203,7 @@ void mmu_invalidate(hart_t *vm)
197203 vm -> cache_store [set ].ways [way ].n_pages = 0xFFFFFFFF ;
198204 vm -> cache_store [set ].lru = 0 ; /* Reset LRU to way 0 */
199205 }
206+ icache_invalidate_all (vm );
200207}
201208
202209/* Invalidate MMU caches for a specific virtual address range.
@@ -361,11 +368,27 @@ static void mmu_fence(hart_t *vm, uint32_t insn UNUSED)
361368
362369static void mmu_fetch (hart_t * vm , uint32_t addr , uint32_t * value )
363370{
364- uint32_t vpn = addr >> RV_PAGE_SHIFT ;
365- if (unlikely (vpn != vm -> cache_fetch .n_pages )) {
371+ /* cache hit */
372+ uint32_t idx = (addr >> ICACHE_OFFSET_BITS ) & ICACHE_INDEX_MASK ;
373+ uint32_t tag = addr >> (ICACHE_OFFSET_BITS + ICACHE_INDEX_BITS );
374+ icache_block_t * blk = & vm -> icache .block [idx ];
375+
376+ if (likely (blk -> valid && blk -> tag == tag )) {
366377#ifdef MMU_CACHE_STATS
367- vm -> cache_fetch .misses ++ ;
378+ vm -> cache_fetch .hits ++ ;
368379#endif
380+ uint32_t ofs = addr & ICACHE_BLOCK_MASK ;
381+ * value = * (const uint32_t * ) (blk -> base + ofs );
382+ return ;
383+ }
384+
385+ #ifdef MMU_CACHE_STATS
386+ vm -> cache_fetch .misses ++ ;
387+ #endif
388+
389+ /* cache miss, Continue using the original va->pa*/
390+ uint32_t vpn = addr >> RV_PAGE_SHIFT ;
391+ if (unlikely (vpn != vm -> cache_fetch .n_pages )) {
369392 mmu_translate (vm , & addr , (1 << 3 ), (1 << 6 ), false, RV_EXC_FETCH_FAULT ,
370393 RV_EXC_FETCH_PFAULT );
371394 if (vm -> error )
@@ -377,12 +400,14 @@ static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
377400 vm -> cache_fetch .n_pages = vpn ;
378401 vm -> cache_fetch .page_addr = page_addr ;
379402 }
380- #ifdef MMU_CACHE_STATS
381- else {
382- vm -> cache_fetch .hits ++ ;
383- }
384- #endif
403+
385404 * value = vm -> cache_fetch .page_addr [(addr >> 2 ) & MASK (RV_PAGE_SHIFT - 2 )];
405+
406+ /* fill into the cache */
407+ uint32_t block_off = (addr & RV_PAGE_MASK ) & ~ICACHE_BLOCK_MASK ;
408+ blk -> base = (const uint8_t * ) vm -> cache_fetch .page_addr + block_off ;
409+ blk -> tag = tag ;
410+ blk -> valid = true;
386411}
387412
388413static void mmu_load (hart_t * vm ,
0 commit comments