Skip to content

Commit 73b1ba5

Browse files
committed
Support just-in-time (JIT) with system simulation
This commit introduces "satp" field to the block structure in JIT mode to ensure the block cache is replaced correctly. The MOP fusion and T2C are disabled temporarily. Use the following commands to boot Linux Kernel: $ make ENABLE_SYSTEM=1 ENABLE_MOP_FUSION=0 ENABLE_JIT=1 ENABLE_T2C=0 $ ./build/rv32emu -k <image> -i <rootfs> -b <dtb>
1 parent a4d3eb1 commit 73b1ba5

File tree

11 files changed

+918
-181
lines changed

11 files changed

+918
-181
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ ifeq ($(call has, JIT), 1)
188188
ifeq ("$(CHECK_LLVM_LIBS)", "0")
189189
OBJS_EXT += t2c.o
190190
CFLAGS += -g $(shell $(LLVM_CONFIG) --cflags)
191-
LDFLAGS += $(shell $(LLVM_CONFIG) --libs)
191+
LDFLAGS += $(shell $(LLVM_CONFIG) --libfiles)
192192
else
193193
$(error No llvm-config-18 installed. Check llvm-config-18 installation in advance, or use "ENABLE_T2C=0" to disable tier-2 LLVM compiler)
194194
endif

src/decode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ typedef struct {
288288
struct rv_insn *target[HISTORY_SIZE];
289289
#else
290290
uint32_t times[HISTORY_SIZE];
291+
#if RV32_HAS(SYSTEM)
292+
uint32_t satp[HISTORY_SIZE];
293+
#endif
291294
#endif
292295
} branch_history_table_t;
293296

src/emulate.c

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ extern struct target_ops gdbstub_ops;
4242
#define IF_imm(i, v) (i->imm == v)
4343

4444
#if RV32_HAS(SYSTEM)
45+
#if !RV32_HAS(JIT)
4546
static bool need_clear_block_map = false;
47+
#endif
4648
static uint32_t reloc_enable_mmu_jalr_addr;
4749
static bool reloc_enable_mmu = false;
4850
bool need_retranslate = false;
@@ -704,6 +706,7 @@ static inline void remove_next_nth_ir(const riscv_t *rv,
704706
* Strategies are being devised to increase the number of instructions that
705707
* match the pattern, including possible instruction reordering.
706708
*/
709+
#if RV32_HAS(MOP_FUSION)
707710
static void match_pattern(riscv_t *rv, block_t *block)
708711
{
709712
uint32_t i;
@@ -795,7 +798,7 @@ static void match_pattern(riscv_t *rv, block_t *block)
795798
}
796799
}
797800
}
798-
801+
#endif
799802
typedef struct {
800803
bool is_constant[N_RV_REGS];
801804
uint32_t const_val[N_RV_REGS];
@@ -838,12 +841,11 @@ static block_t *block_find_or_translate(riscv_t *rv)
838841
block_t *next_blk = block_find(map, rv->PC);
839842
#else
840843
/* lookup the next block in the block cache */
841-
/*
842-
* The function "cache_get()" gets the cached block by the given "key (PC)".
843-
* In system simulation, the returned block might be dropped because it is
844-
* not the one from the current process (by checking SATP CSR register).
845-
*/
846844
block_t *next_blk = (block_t *) cache_get(rv->block_cache, rv->PC, true);
845+
#if RV32_HAS(SYSTEM)
846+
if (next_blk && next_blk->satp != rv->csr_satp)
847+
next_blk = NULL;
848+
#endif
847849
#endif
848850

849851
if (next_blk)
@@ -861,12 +863,20 @@ static block_t *block_find_or_translate(riscv_t *rv)
861863

862864
block_translate(rv, next_blk);
863865

866+
#if RV32_HAS(JIT) && RV32_HAS(SYSTEM)
867+
/*
868+
* may be an ifetch fault which changes satp, Do not do this
869+
* in "block_alloc()
870+
*/
871+
next_blk->satp = rv->csr_satp;
872+
#endif
873+
864874
optimize_constant(rv, next_blk);
875+
865876
#if RV32_HAS(GDBSTUB)
866877
if (likely(!rv->debug_mode))
867878
#endif
868-
#if RV32_HAS(MOP_FUSION)
869-
/* macro operation fusion */
879+
#if RV32_HAS(GDBSTUB) || RV32_HAS(MOP_FUSION)
870880
match_pattern(rv, next_blk);
871881
#endif
872882

@@ -890,8 +900,6 @@ static block_t *block_find_or_translate(riscv_t *rv)
890900
return next_blk;
891901
}
892902

893-
list_del_init(&replaced_blk->list);
894-
895903
if (prev == replaced_blk)
896904
prev = NULL;
897905

@@ -910,6 +918,32 @@ static block_t *block_find_or_translate(riscv_t *rv)
910918
if (untaken == replaced_blk_entry) {
911919
entry->ir_tail->branch_untaken = NULL;
912920
}
921+
922+
/* upadte JALR LUT */
923+
if (!entry->ir_tail->branch_table)
924+
continue;
925+
926+
#if 0
927+
/*
928+
* This branch lookup updating is unused since we get the PC from it and
929+
* use function "cache_get()" achieve the branch prediction of T1C.
930+
* However, if the structure "branch_table_t" is going to reference the
931+
* block directly, this updating is nacessary to avoid to use the freed
932+
* blocks.
933+
*/
934+
for (int i = 0; i < HISTORY_SIZE; i++) {
935+
if (entry->ir_tail->branch_table->PC[i] == replaced_blk->pc_start) {
936+
IIF(RV32_HAS(SYSTEM))
937+
(if (entry->ir_tail->branch_table->satp[i] ==
938+
replaced_blk->satp), )
939+
{
940+
entry->ir_tail->branch_table->PC[i] =
941+
entry->ir_tail->branch_table->satp[i] =
942+
entry->ir_tail->branch_table->times[i] = 0;
943+
}
944+
}
945+
}
946+
#endif
913947
}
914948

915949
/* free IRs in replaced block */
@@ -923,6 +957,7 @@ static block_t *block_find_or_translate(riscv_t *rv)
923957
mpool_free(rv->block_ir_mp, ir);
924958
}
925959

960+
list_del_init(&replaced_blk->list);
926961
mpool_free(rv->block_mp, replaced_blk);
927962
#if RV32_HAS(T2C)
928963
pthread_mutex_unlock(&rv->cache_lock);
@@ -941,6 +976,10 @@ static bool runtime_profiler(riscv_t *rv, block_t *block)
941976
* we posit that our profiler could effectively identify hotspots using
942977
* three key indicators.
943978
*/
979+
#if RV32_HAS(SYSTEM)
980+
if (block->satp != rv->csr_satp)
981+
return false;
982+
#endif
944983
uint32_t freq = cache_freq(rv->block_cache, block->pc_start);
945984
/* To profile a block after chaining, it must first be executed. */
946985
if (unlikely(freq >= 2 && block->has_loops))
@@ -1022,15 +1061,21 @@ void rv_step(void *arg)
10221061
block_t *block = block_find_or_translate(rv);
10231062
/* by now, a block should be available */
10241063
assert(block);
1064+
#if RV32_HAS(JIT) && RV32_HAS(SYSTEM)
1065+
assert(block->satp == rv->csr_satp);
1066+
#endif
10251067

10261068
/* After emulating the previous block, it is determined whether the
10271069
* branch is taken or not. The IR array of the current block is then
10281070
* assigned to either the branch_taken or branch_untaken pointer of
10291071
* the previous block.
10301072
*/
1031-
10321073
#if RV32_HAS(BLOCK_CHAINING)
1033-
if (prev) {
1074+
if (prev
1075+
#if RV32_HAS(JIT) && RV32_HAS(SYSTEM)
1076+
&& prev->satp == rv->csr_satp
1077+
#endif
1078+
) {
10341079
rv_insn_t *last_ir = prev->ir_tail;
10351080
/* chain block */
10361081
if (!insn_is_unconditional_branch(last_ir->opcode)) {
@@ -1048,7 +1093,7 @@ void rv_step(void *arg)
10481093
#endif
10491094
last_pc = rv->PC;
10501095
#if RV32_HAS(JIT)
1051-
#if RV32_HAS(T2C)
1096+
#if RV32_HAS(T2C) && !RV32_HAS(SYSTEM)
10521097
/* executed through the tier-2 JIT compiler */
10531098
if (block->hot2) {
10541099
((exec_t2c_func_t) block->func)(rv);

0 commit comments

Comments
 (0)