-
Notifications
You must be signed in to change notification settings - Fork 63
Implement direct mapped cache for instruction fetch #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,7 +75,55 @@ typedef struct { | |
| typedef struct __hart_internal hart_t; | ||
| typedef struct __vm_internel vm_t; | ||
|
|
||
| /* ICACHE_BLOCKS_SIZE: Size of one instruction-cache block (line). | ||
| * ICACHE_BLOCKS: Number of blocks (lines) in the instruction cache. | ||
| * | ||
| * The cache address is decomposed into [ tag | index | offset ] fields: | ||
| * - block-offset bits = log2(ICACHE_BLOCKS_SIZE) | ||
| * - index bits = log2(ICACHE_BLOCKS) | ||
| * | ||
| * For power-of-two values, log2(x) equals the number of trailing zero bits in | ||
| * x. Therefore, we use __builtin_ctz(x) (count trailing zeros) to compute these | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not worthy to invoke There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason it was designed this way is because I initially needed to experiment with various cache size combinations. - #define ICACHE_OFFSET_BITS (__builtin_ctz((ICACHE_BLOCKS_SIZE)))
- #define ICACHE_INDEX_BITS (__builtin_ctz((ICACHE_BLOCKS)))
+ #define ICACHE_OFFSET_BITS 8
+ #define ICACHE_INDEX_BITS 8 |
||
| * log2 values at compile time. | ||
| */ | ||
| #define ICACHE_BLOCKS_SIZE 256 | ||
| #define ICACHE_BLOCKS 256 | ||
| #define ICACHE_OFFSET_BITS (__builtin_ctz((ICACHE_BLOCKS_SIZE))) | ||
| #define ICACHE_INDEX_BITS (__builtin_ctz((ICACHE_BLOCKS))) | ||
|
|
||
| /* Define the victim cache. | ||
| * | ||
| * The block size of the victim cache is identical to that of the primary | ||
| * instruction cache (IC), ensuring full block compatibility. | ||
| * However, the number of blocks is smaller, allowing the VC to store | ||
| * a few recently evicted cache lines to reduce conflict misses. | ||
| */ | ||
| #define VCACHE_BLOCK_SIZE ICACHE_BLOCKS_SIZE | ||
| #define VCACHE_BLOCKS 16 | ||
|
|
||
| /* For power-of-two sizes, (size - 1) sets all low bits to 1, | ||
| * allowing fast extraction of an address. | ||
| */ | ||
| #define ICACHE_INDEX_MASK (ICACHE_BLOCKS - 1) | ||
| #define ICACHE_BLOCK_MASK (ICACHE_BLOCKS_SIZE - 1) | ||
| #define RV_PAGE_MASK (RV_PAGE_SIZE - 1) | ||
|
|
||
| typedef struct { | ||
| uint32_t tag; | ||
| const uint8_t *base; | ||
| bool valid; | ||
| } icache_block_t; | ||
|
|
||
| typedef icache_block_t victim_cache_block_t; | ||
|
|
||
| typedef struct { | ||
| icache_block_t i_block[ICACHE_BLOCKS]; | ||
| victim_cache_block_t v_block[VCACHE_BLOCKS]; | ||
| uint32_t v_next; | ||
| } icache_t; | ||
|
|
||
| struct __hart_internal { | ||
| icache_t icache; | ||
| uint32_t x_regs[32]; | ||
|
|
||
| /* LR reservation virtual address. last bit is 1 if valid */ | ||
|
|
@@ -106,7 +154,8 @@ struct __hart_internal { | |
| */ | ||
| uint32_t exc_cause, exc_val; | ||
|
|
||
| mmu_fetch_cache_t cache_fetch; | ||
| /* 2-entry direct-mapped with hash-based indexing */ | ||
| mmu_fetch_cache_t cache_fetch[2]; | ||
| /* 8-set × 2-way set-associative cache with 3-bit parity hash indexing */ | ||
| mmu_cache_set_t cache_load[8]; | ||
| /* 8-set × 2-way set-associative cache for store operations */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code looks suspicious to me.
When you move the evicted I-cache block (tmp) back into the victim cache, you are setting the vblk->tag to tmp.tag, which is the 16-bit I-cache tag.
Won't this corrupts the victim cache entry? The VC search logic requires a 24-bit tag ([ICache Tag | ICache Index]) to function. Because you're only storing the 16-bit tag, this VCache entry will never be hit again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing that out. I’ve added the following expressions to ensure correctness :
+ vblk->tag = (tmp.tag << ICACHE_INDEX_BITS) | idx;