Skip to content

Commit 7277124

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 e2a5b74 commit 7277124

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
/* Pre-verify the root page table to minimize page table access during
@@ -310,11 +317,27 @@ static void mmu_fence(hart_t *vm, uint32_t insn UNUSED)
310317

311318
static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
312319
{
313-
uint32_t vpn = addr >> RV_PAGE_SHIFT;
314-
if (unlikely(vpn != vm->cache_fetch.n_pages)) {
320+
/* cache hit */
321+
uint32_t idx = (addr >> IC_SHIFT) & IC_INDEX_MASK;
322+
uint32_t tag = addr >> (IC_SHIFT + IC_INDEX_BITS);
323+
ic_block_t *blk = &vm->ic.block[idx];
324+
325+
if (likely(blk->valid && blk->tag == tag)) {
315326
#ifdef MMU_CACHE_STATS
316-
vm->cache_fetch.misses++;
327+
vm->cache_fetch.hits++;
317328
#endif
329+
uint32_t ofs = addr & IC_BLOCK_MASK;
330+
*value = *(const uint32_t *) (blk->base + ofs);
331+
return;
332+
}
333+
334+
#ifdef MMU_CACHE_STATS
335+
vm->cache_fetch.misses++;
336+
#endif
337+
338+
/* cache miss, Continue using the original va->pa*/
339+
uint32_t vpn = addr >> RV_PAGE_SHIFT;
340+
if (unlikely(vpn != vm->cache_fetch.n_pages)) {
318341
mmu_translate(vm, &addr, (1 << 3), (1 << 6), false, RV_EXC_FETCH_FAULT,
319342
RV_EXC_FETCH_PFAULT);
320343
if (vm->error)
@@ -326,12 +349,14 @@ static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
326349
vm->cache_fetch.n_pages = vpn;
327350
vm->cache_fetch.page_addr = page_addr;
328351
}
329-
#ifdef MMU_CACHE_STATS
330-
else {
331-
vm->cache_fetch.hits++;
332-
}
333-
#endif
352+
334353
*value = vm->cache_fetch.page_addr[(addr >> 2) & MASK(RV_PAGE_SHIFT - 2)];
354+
355+
/* fill into the cache */
356+
uint32_t block_off = (addr & RV_PAGE_MASK) & ~IC_BLOCK_MASK;
357+
blk->base = (const uint8_t *) vm->cache_fetch.page_addr + block_off;
358+
blk->tag = addr >> (IC_SHIFT + IC_INDEX_BITS);
359+
blk->valid = true;
335360
}
336361

337362
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)