Skip to content

Commit 8825b96

Browse files
committed
Implement direct mapped cache for instruction fetch
Extend the existing architecture to cache the last fetched PC instruction, improving instruction fetch hit rate by approximately 2%. Also includes clang-format fixes for several expressions.
1 parent 51e1115 commit 8825b96

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

riscv.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
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

185191
void 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+
ic_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

362369
static 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 >> IC_SHIFT) & IC_INDEX_MASK;
373+
uint32_t tag = addr >> (IC_SHIFT + IC_INDEX_BITS);
374+
ic_block_t *blk = &vm->ic.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 & IC_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) & ~IC_BLOCK_MASK;
408+
blk->base = (const uint8_t *) vm->cache_fetch.page_addr + block_off;
409+
blk->tag = addr >> (IC_SHIFT + IC_INDEX_BITS);
410+
blk->valid = true;
386411
}
387412

388413
static void mmu_load(hart_t *vm,

riscv.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,26 @@ typedef struct {
7575
typedef struct __hart_internal hart_t;
7676
typedef struct __vm_internel vm_t;
7777

78+
#define IC_BLOCKS_SIZE 256
79+
#define IC_BLOCKS 256
80+
#define IC_SHIFT (__builtin_ctz((IC_BLOCKS_SIZE)))
81+
#define IC_INDEX_BITS (__builtin_ctz((IC_BLOCKS)))
82+
#define IC_INDEX_MASK (IC_BLOCKS - 1)
83+
#define IC_BLOCK_MASK (IC_BLOCKS_SIZE - 1)
84+
#define RV_PAGE_MASK (RV_PAGE_SIZE - 1)
85+
86+
typedef struct {
87+
uint32_t tag;
88+
const uint8_t *base;
89+
bool valid;
90+
} ic_block_t;
91+
92+
typedef struct {
93+
ic_block_t block[IC_BLOCKS];
94+
} ic_t;
95+
7896
struct __hart_internal {
97+
ic_t ic;
7998
uint32_t x_regs[32];
8099

81100
/* LR reservation virtual address. last bit is 1 if valid */

0 commit comments

Comments
 (0)