Skip to content

Commit bb9e6cb

Browse files
committed
Refactor and document I-cache, fix tag calculation
- Rename I-cache structures from ic to icache to avoid ambiguity. - Add explanations for instruction-cache definitions and masks, and align the macro names with the terminology used in the comments. - Fix tag calculation to use the precomputed tag rather than shifting the physical address.
1 parent 0e4f67b commit bb9e6cb

File tree

6 files changed

+170
-145
lines changed

6 files changed

+170
-145
lines changed

.smp_stamp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"files.associations": {
3+
"unistd.h": "c",
4+
"stdbool.h": "c"
5+
}
6+
}

main.c

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,9 @@ static inline sbi_ret_t handle_sbi_ecall_TIMER(hart_t *hart, int32_t fid)
342342
(((uint64_t) hart->x_regs[RV_R_A1]) << 32) |
343343
(uint64_t) (hart->x_regs[RV_R_A0]);
344344
hart->sip &= ~RV_INT_STI_BIT;
345-
return (sbi_ret_t){SBI_SUCCESS, 0};
345+
return (sbi_ret_t) {SBI_SUCCESS, 0};
346346
default:
347-
return (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
347+
return (sbi_ret_t) {SBI_ERR_NOT_SUPPORTED, 0};
348348
}
349349
}
350350

@@ -356,9 +356,9 @@ static inline sbi_ret_t handle_sbi_ecall_RST(hart_t *hart, int32_t fid)
356356
fprintf(stderr, "system reset: type=%u, reason=%u\n",
357357
hart->x_regs[RV_R_A0], hart->x_regs[RV_R_A1]);
358358
data->stopped = true;
359-
return (sbi_ret_t){SBI_SUCCESS, 0};
359+
return (sbi_ret_t) {SBI_SUCCESS, 0};
360360
default:
361-
return (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
361+
return (sbi_ret_t) {SBI_ERR_NOT_SUPPORTED, 0};
362362
}
363363
}
364364

@@ -378,13 +378,13 @@ static inline sbi_ret_t handle_sbi_ecall_HSM(hart_t *hart, int32_t fid)
378378
vm->hart[hartid]->x_regs[RV_R_A1] = opaque;
379379
vm->hart[hartid]->pc = start_addr;
380380
vm->hart[hartid]->s_mode = true;
381-
return (sbi_ret_t){SBI_SUCCESS, 0};
381+
return (sbi_ret_t) {SBI_SUCCESS, 0};
382382
case SBI_HSM__HART_STOP:
383383
hart->hsm_status = SBI_HSM_STATE_STOPPED;
384-
return (sbi_ret_t){SBI_SUCCESS, 0};
384+
return (sbi_ret_t) {SBI_SUCCESS, 0};
385385
case SBI_HSM__HART_GET_STATUS:
386386
hartid = hart->x_regs[RV_R_A0];
387-
return (sbi_ret_t){SBI_SUCCESS, vm->hart[hartid]->hsm_status};
387+
return (sbi_ret_t) {SBI_SUCCESS, vm->hart[hartid]->hsm_status};
388388
case SBI_HSM__HART_SUSPEND:
389389
suspend_type = hart->x_regs[RV_R_A0];
390390
resume_addr = hart->x_regs[RV_R_A1];
@@ -398,11 +398,11 @@ static inline sbi_ret_t handle_sbi_ecall_HSM(hart_t *hart, int32_t fid)
398398
hart->hsm_resume_pc = resume_addr;
399399
hart->hsm_resume_opaque = opaque;
400400
}
401-
return (sbi_ret_t){SBI_SUCCESS, 0};
401+
return (sbi_ret_t) {SBI_SUCCESS, 0};
402402
default:
403-
return (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
403+
return (sbi_ret_t) {SBI_ERR_NOT_SUPPORTED, 0};
404404
}
405-
return (sbi_ret_t){SBI_ERR_FAILED, 0};
405+
return (sbi_ret_t) {SBI_ERR_FAILED, 0};
406406
}
407407

408408
static inline sbi_ret_t handle_sbi_ecall_IPI(hart_t *hart, int32_t fid)
@@ -421,10 +421,10 @@ static inline sbi_ret_t handle_sbi_ecall_IPI(hart_t *hart, int32_t fid)
421421
data->sswi.ssip[i] = hart_mask & 1;
422422
}
423423

424-
return (sbi_ret_t){SBI_SUCCESS, 0};
424+
return (sbi_ret_t) {SBI_SUCCESS, 0};
425425
break;
426426
default:
427-
return (sbi_ret_t){SBI_ERR_FAILED, 0};
427+
return (sbi_ret_t) {SBI_ERR_FAILED, 0};
428428
}
429429
}
430430

@@ -439,7 +439,7 @@ static inline sbi_ret_t handle_sbi_ecall_RFENCE(hart_t *hart, int32_t fid)
439439
uint64_t hart_mask, hart_mask_base;
440440
switch (fid) {
441441
case 0:
442-
return (sbi_ret_t){SBI_SUCCESS, 0};
442+
return (sbi_ret_t) {SBI_SUCCESS, 0};
443443
case 1:
444444
hart_mask = (uint64_t) hart->x_regs[RV_R_A0];
445445
hart_mask_base = (uint64_t) hart->x_regs[RV_R_A1];
@@ -452,16 +452,16 @@ static inline sbi_ret_t handle_sbi_ecall_RFENCE(hart_t *hart, int32_t fid)
452452
mmu_invalidate(hart->vm->hart[i]);
453453
}
454454
}
455-
return (sbi_ret_t){SBI_SUCCESS, 0};
455+
return (sbi_ret_t) {SBI_SUCCESS, 0};
456456
case 2:
457457
case 3:
458458
case 4:
459459
case 5:
460460
case 6:
461461
case 7:
462-
return (sbi_ret_t){SBI_SUCCESS, 0};
462+
return (sbi_ret_t) {SBI_SUCCESS, 0};
463463
default:
464-
return (sbi_ret_t){SBI_ERR_FAILED, 0};
464+
return (sbi_ret_t) {SBI_ERR_FAILED, 0};
465465
}
466466
}
467467

@@ -473,26 +473,26 @@ static inline sbi_ret_t handle_sbi_ecall_BASE(hart_t *hart, int32_t fid)
473473
{
474474
switch (fid) {
475475
case SBI_BASE__GET_SBI_IMPL_ID:
476-
return (sbi_ret_t){SBI_SUCCESS, SBI_IMPL_ID};
476+
return (sbi_ret_t) {SBI_SUCCESS, SBI_IMPL_ID};
477477
case SBI_BASE__GET_SBI_IMPL_VERSION:
478-
return (sbi_ret_t){SBI_SUCCESS, SBI_IMPL_VERSION};
478+
return (sbi_ret_t) {SBI_SUCCESS, SBI_IMPL_VERSION};
479479
case SBI_BASE__GET_MVENDORID:
480-
return (sbi_ret_t){SBI_SUCCESS, RV_MVENDORID};
480+
return (sbi_ret_t) {SBI_SUCCESS, RV_MVENDORID};
481481
case SBI_BASE__GET_MARCHID:
482-
return (sbi_ret_t){SBI_SUCCESS, RV_MARCHID};
482+
return (sbi_ret_t) {SBI_SUCCESS, RV_MARCHID};
483483
case SBI_BASE__GET_MIMPID:
484-
return (sbi_ret_t){SBI_SUCCESS, RV_MIMPID};
484+
return (sbi_ret_t) {SBI_SUCCESS, RV_MIMPID};
485485
case SBI_BASE__GET_SBI_SPEC_VERSION:
486-
return (sbi_ret_t){SBI_SUCCESS, (2 << 24) | 0}; /* version 2.0 */
486+
return (sbi_ret_t) {SBI_SUCCESS, (2 << 24) | 0}; /* version 2.0 */
487487
case SBI_BASE__PROBE_EXTENSION: {
488488
int32_t eid = (int32_t) hart->x_regs[RV_R_A0];
489489
bool available = eid == SBI_EID_BASE || eid == SBI_EID_TIMER ||
490490
eid == SBI_EID_RST || eid == SBI_EID_HSM ||
491491
eid == SBI_EID_IPI || eid == SBI_EID_RFENCE;
492-
return (sbi_ret_t){SBI_SUCCESS, available};
492+
return (sbi_ret_t) {SBI_SUCCESS, available};
493493
}
494494
default:
495-
return (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
495+
return (sbi_ret_t) {SBI_ERR_NOT_SUPPORTED, 0};
496496
}
497497
}
498498

@@ -522,7 +522,7 @@ static void handle_sbi_ecall(hart_t *hart)
522522
SBI_HANDLE(RFENCE);
523523
break;
524524
default:
525-
ret = (sbi_ret_t){SBI_ERR_NOT_SUPPORTED, 0};
525+
ret = (sbi_ret_t) {SBI_ERR_NOT_SUPPORTED, 0};
526526
}
527527
hart->x_regs[RV_R_A0] = (uint32_t) ret.error;
528528
hart->x_regs[RV_R_A1] = (uint32_t) ret.value;
@@ -1037,8 +1037,8 @@ static int semu_run(emu_state_t *emu)
10371037
#else
10381038
/* Linux: poll on timerfd and UART */
10391039
struct pollfd pfds[2];
1040-
pfds[0] = (struct pollfd){wfi_timer_fd, POLLIN, 0};
1041-
pfds[1] = (struct pollfd){emu->uart.in_fd, POLLIN, 0};
1040+
pfds[0] = (struct pollfd) {wfi_timer_fd, POLLIN, 0};
1041+
pfds[1] = (struct pollfd) {emu->uart.in_fd, POLLIN, 0};
10421042
poll(pfds, 2, -1);
10431043

10441044
/* Consume timerfd event to prevent accumulation */
@@ -1220,7 +1220,7 @@ static int semu_run_debug(emu_state_t *emu)
12201220

12211221
emu->curr_cpuid = 0;
12221222
if (!gdbstub_init(&gdbstub, &gdbstub_ops,
1223-
(arch_info_t){
1223+
(arch_info_t) {
12241224
.smp = vm->n_hart,
12251225
.reg_num = 33,
12261226
.target_desc = TARGET_RV32,

riscv.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,9 @@ static void mmu_fence(hart_t *vm, uint32_t insn UNUSED)
309309
static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
310310
{
311311
/* 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];
312+
uint32_t idx = (addr >> IC_OFFSET_BITS) & IC_INDEX_MASK;
313+
uint32_t tag = addr >> (IC_OFFSET_BITS + IC_INDEX_BITS);
314+
icache_block_t *blk = &vm->ic.block[idx];
315315

316316
if (likely(blk->valid && blk->tag == tag)) {
317317
#ifdef MMU_CACHE_STATS
@@ -346,7 +346,7 @@ static void mmu_fetch(hart_t *vm, uint32_t addr, uint32_t *value)
346346
/* fill into the cache */
347347
uint32_t block_off = (addr & RV_PAGE_MASK) & ~IC_BLOCK_MASK;
348348
blk->base = (const uint8_t *) vm->cache_fetch.page_addr + block_off;
349-
blk->tag = addr >> (IC_SHIFT + IC_INDEX_BITS);
349+
blk->tag = tag;
350350
blk->valid = true;
351351
}
352352

riscv.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,25 @@ typedef struct {
6969
typedef struct __hart_internal hart_t;
7070
typedef struct __vm_internel vm_t;
7171

72+
/* IC_BLOCKS_SIZE: Size of one instruction-cache block (line).
73+
* IC_BLOCKS: Number of blocks (lines) in the instruction cache.
74+
*
75+
* The cache address is decomposed into [ tag | index | offset ] fields:
76+
* - block-offset bits = log2(IC_BLOCKS_SIZE)
77+
* - index bits = log2(IC_BLOCKS)
78+
*
79+
* For power-of-two values, log2(x) equals the number of trailing zero bits in
80+
* x. Therefore, we use __builtin_ctz(x) (count trailing zeros) to compute these
81+
* log2 values at compile time.
82+
*/
7283
#define IC_BLOCKS_SIZE 256
7384
#define IC_BLOCKS 256
74-
#define IC_SHIFT (__builtin_ctz((IC_BLOCKS_SIZE)))
85+
#define IC_OFFSET_BITS (__builtin_ctz((IC_BLOCKS_SIZE)))
7586
#define IC_INDEX_BITS (__builtin_ctz((IC_BLOCKS)))
87+
88+
/* For power-of-two sizes, (size - 1) sets all low bits to 1,
89+
* allowing fast extraction of an address.
90+
*/
7691
#define IC_INDEX_MASK (IC_BLOCKS - 1)
7792
#define IC_BLOCK_MASK (IC_BLOCKS_SIZE - 1)
7893
#define RV_PAGE_MASK (RV_PAGE_SIZE - 1)
@@ -81,14 +96,14 @@ typedef struct {
8196
uint32_t tag;
8297
const uint8_t *base;
8398
bool valid;
84-
} ic_block_t;
99+
} icache_block_t;
85100

86101
typedef struct {
87-
ic_block_t block[IC_BLOCKS];
88-
} ic_t;
102+
icache_block_t block[IC_BLOCKS];
103+
} icache_t;
89104

90105
struct __hart_internal {
91-
ic_t ic;
106+
icache_t ic;
92107
uint32_t x_regs[32];
93108

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

0 commit comments

Comments
 (0)