Skip to content

Commit 8f44788

Browse files
authored
Merge pull request #593 from vacantron/fix/t2c
Fix T2C in system simulation
2 parents c168617 + 308fad2 commit 8f44788

File tree

6 files changed

+290
-101
lines changed

6 files changed

+290
-101
lines changed

.github/workflows/main.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ jobs:
279279
env:
280280
CC: ${{ steps.install_cc.outputs.cc }}
281281
run: |
282-
make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL
282+
make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL
283283
bash -c "${BOOT_LINUX_TEST}"
284-
make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 clean
284+
make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 clean
285285
if: ${{ always() }}
286286
- name: Architecture test
287287
env:
@@ -484,9 +484,9 @@ jobs:
484484
env:
485485
CC: ${{ steps.install_cc.outputs.cc }}
486486
run: |
487-
make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL
487+
make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL
488488
bash -c "${BOOT_LINUX_TEST}"
489-
make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 clean
489+
make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 clean
490490
if: ${{ always() }}
491491
- name: Architecture test
492492
env:

src/jit.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ typedef void (*exec_t2c_func_t)(riscv_t *);
7171
#define N_JIT_CACHE_ENTRIES (1 << 12)
7272

7373
struct jit_cache {
74-
uint64_t pc; /* program counter, easy to build LLVM IR with 64-bit width */
75-
void *entry; /* entry of JIT-ed code */
74+
uint64_t key; /* program counter, composed to satp if it's in system
75+
simulation */
76+
void *entry; /* entry of JIT-ed code */
7677
};
7778

7879
struct jit_cache *jit_cache_init();
7980
void jit_cache_exit(struct jit_cache *cache);
80-
void jit_cache_update(struct jit_cache *cache, uint32_t pc, void *entry);
81+
void jit_cache_update(struct jit_cache *cache, uint64_t key, void *entry);
8182
void jit_cache_clear(struct jit_cache *cache);
8283
#endif

src/system.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ static uint32_t mmu_ifetch(riscv_t *rv, const uint32_t vaddr)
216216
return memory_ifetch(ppn | offset);
217217
}
218218

219-
static uint32_t mmu_read_w(riscv_t *rv, const uint32_t vaddr)
219+
uint32_t mmu_read_w(riscv_t *rv, const uint32_t vaddr)
220220
{
221221
uint32_t addr = rv->io.mem_translate(rv, vaddr, R);
222222

@@ -235,7 +235,7 @@ static uint32_t mmu_read_w(riscv_t *rv, const uint32_t vaddr)
235235
__UNREACHABLE;
236236
}
237237

238-
static uint16_t mmu_read_s(riscv_t *rv, const uint32_t vaddr)
238+
uint16_t mmu_read_s(riscv_t *rv, const uint32_t vaddr)
239239
{
240240
uint32_t addr = rv->io.mem_translate(rv, vaddr, R);
241241

@@ -247,7 +247,7 @@ static uint16_t mmu_read_s(riscv_t *rv, const uint32_t vaddr)
247247
return memory_read_s(addr);
248248
}
249249

250-
static uint8_t mmu_read_b(riscv_t *rv, const uint32_t vaddr)
250+
uint8_t mmu_read_b(riscv_t *rv, const uint32_t vaddr)
251251
{
252252
uint32_t addr = rv->io.mem_translate(rv, vaddr, R);
253253

@@ -266,7 +266,7 @@ static uint8_t mmu_read_b(riscv_t *rv, const uint32_t vaddr)
266266
__UNREACHABLE;
267267
}
268268

269-
static void mmu_write_w(riscv_t *rv, const uint32_t vaddr, const uint32_t val)
269+
void mmu_write_w(riscv_t *rv, const uint32_t vaddr, const uint32_t val)
270270
{
271271
uint32_t addr = rv->io.mem_translate(rv, vaddr, W);
272272

@@ -285,7 +285,7 @@ static void mmu_write_w(riscv_t *rv, const uint32_t vaddr, const uint32_t val)
285285
#endif
286286
}
287287

288-
static void mmu_write_s(riscv_t *rv, const uint32_t vaddr, const uint16_t val)
288+
void mmu_write_s(riscv_t *rv, const uint32_t vaddr, const uint16_t val)
289289
{
290290
uint32_t addr = rv->io.mem_translate(rv, vaddr, W);
291291

@@ -300,7 +300,7 @@ static void mmu_write_s(riscv_t *rv, const uint32_t vaddr, const uint16_t val)
300300
memory_write_s(addr, (uint8_t *) &val);
301301
}
302302

303-
static void mmu_write_b(riscv_t *rv, const uint32_t vaddr, const uint8_t val)
303+
void mmu_write_b(riscv_t *rv, const uint32_t vaddr, const uint8_t val)
304304
{
305305
uint32_t addr = rv->io.mem_translate(rv, vaddr, W);
306306

src/system.h

+7
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,10 @@ uint32_t *mmu_walk(riscv_t *rv, const uint32_t addr, uint32_t *level);
173173
offset = level == 1 ? vaddr & MASK((RV_PG_SHIFT + 10)) \
174174
: vaddr & MASK(RV_PG_SHIFT); \
175175
} while (0)
176+
177+
uint8_t mmu_read_b(riscv_t *rv, const uint32_t vaddr);
178+
uint16_t mmu_read_s(riscv_t *rv, const uint32_t vaddr);
179+
uint32_t mmu_read_w(riscv_t *rv, const uint32_t vaddr);
180+
void mmu_write_b(riscv_t *rv, const uint32_t vaddr, const uint8_t val);
181+
void mmu_write_s(riscv_t *rv, const uint32_t vaddr, const uint16_t val);
182+
void mmu_write_w(riscv_t *rv, const uint32_t vaddr, const uint32_t val);

src/t2c.c

+66-40
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,21 @@ FORCE_INLINE LLVMBasicBlockRef t2c_block_map_search(struct LLVM_block_map *map,
4949
return NULL;
5050
}
5151

52-
#define T2C_OP(inst, code) \
53-
static void t2c_##inst( \
54-
LLVMBuilderRef *builder UNUSED, LLVMTypeRef *param_types UNUSED, \
55-
LLVMValueRef start UNUSED, LLVMBasicBlockRef *entry UNUSED, \
56-
LLVMBuilderRef *taken_builder UNUSED, \
57-
LLVMBuilderRef *untaken_builder UNUSED, riscv_t *rv UNUSED, \
58-
uint64_t mem_base UNUSED, rv_insn_t *ir UNUSED) \
59-
{ \
60-
LLVMValueRef timer_ptr = t2c_gen_timer_addr(start, builder, ir); \
61-
LLVMValueRef timer = \
62-
LLVMBuildLoad2(*builder, LLVMInt64Type(), timer_ptr, ""); \
63-
timer = LLVMBuildAdd(*builder, timer, \
64-
LLVMConstInt(LLVMInt64Type(), 1, false), ""); \
65-
LLVMBuildStore(*builder, timer, timer_ptr); \
66-
code; \
52+
#define T2C_OP(inst, code) \
53+
static void t2c_##inst( \
54+
LLVMBuilderRef *builder UNUSED, LLVMTypeRef *param_types UNUSED, \
55+
LLVMValueRef start UNUSED, LLVMBasicBlockRef *entry UNUSED, \
56+
LLVMBuilderRef *taken_builder UNUSED, \
57+
LLVMBuilderRef *untaken_builder UNUSED, riscv_t *rv UNUSED, \
58+
uint64_t mem_base UNUSED, block_t *block UNUSED, rv_insn_t *ir UNUSED) \
59+
{ \
60+
LLVMValueRef timer_ptr = t2c_gen_timer_addr(start, builder, ir); \
61+
LLVMValueRef timer = \
62+
LLVMBuildLoad2(*builder, LLVMInt64Type(), timer_ptr, ""); \
63+
timer = LLVMBuildAdd(*builder, timer, \
64+
LLVMConstInt(LLVMInt64Type(), 1, false), ""); \
65+
LLVMBuildStore(*builder, timer, timer_ptr); \
66+
code; \
6767
}
6868

6969
#define T2C_LLVM_GEN_ADDR(reg, rv_member, ir_member) \
@@ -190,17 +190,20 @@ typedef void (*t2c_codegen_block_func_t)(LLVMBuilderRef *builder UNUSED,
190190
LLVMBuilderRef *untaken_builder UNUSED,
191191
riscv_t *rv UNUSED,
192192
uint64_t mem_base UNUSED,
193+
block_t *block UNUSED,
193194
rv_insn_t *ir UNUSED);
194195

195196
static void t2c_trace_ebb(LLVMBuilderRef *builder,
196197
LLVMTypeRef *param_types UNUSED,
197198
LLVMValueRef start,
198199
LLVMBasicBlockRef *entry,
199200
riscv_t *rv,
200-
rv_insn_t *ir,
201+
block_t *block,
201202
set_t *set,
202203
struct LLVM_block_map *map)
203204
{
205+
rv_insn_t *ir = block->ir_head;
206+
204207
if (set_has(set, ir->pc))
205208
return;
206209
set_add(set, ir->pc);
@@ -210,7 +213,7 @@ static void t2c_trace_ebb(LLVMBuilderRef *builder,
210213
while (1) {
211214
((t2c_codegen_block_func_t) dispatch_table[ir->opcode])(
212215
builder, param_types, start, entry, &tk, &utk, rv,
213-
(uint64_t) ((memory_t *) PRIV(rv)->mem)->mem_base, ir);
216+
(uint64_t) ((memory_t *) PRIV(rv)->mem)->mem_base, block, ir);
214217
if (!ir->next)
215218
break;
216219
ir = ir->next;
@@ -222,30 +225,43 @@ static void t2c_trace_ebb(LLVMBuilderRef *builder,
222225
LLVMBuildBr(utk,
223226
t2c_block_map_search(map, ir->branch_untaken->pc));
224227
else {
225-
LLVMBasicBlockRef untaken_entry =
226-
LLVMAppendBasicBlock(start,
227-
"untaken_"
228-
"entry");
229-
LLVMBuilderRef untaken_builder = LLVMCreateBuilder();
230-
LLVMPositionBuilderAtEnd(untaken_builder, untaken_entry);
231-
LLVMBuildBr(utk, untaken_entry);
232-
t2c_trace_ebb(&untaken_builder, param_types, start,
233-
&untaken_entry, rv, ir->branch_untaken, set, map);
228+
block_t *blk =
229+
cache_get(rv->block_cache, ir->branch_untaken->pc, false);
230+
if (blk && blk->translatable
231+
#if RV32_HAS(SYSTEM)
232+
&& blk->satp == block->satp
233+
#endif
234+
) {
235+
LLVMBasicBlockRef untaken_entry =
236+
LLVMAppendBasicBlock(start, "untaken_entry");
237+
LLVMBuilderRef untaken_builder = LLVMCreateBuilder();
238+
LLVMPositionBuilderAtEnd(untaken_builder, untaken_entry);
239+
LLVMBuildBr(utk, untaken_entry);
240+
t2c_trace_ebb(&untaken_builder, param_types, start,
241+
&untaken_entry, rv, blk, set, map);
242+
}
234243
}
235244
}
236245
if (ir->branch_taken) {
237246
if (set_has(set, ir->branch_taken->pc))
238247
LLVMBuildBr(tk,
239248
t2c_block_map_search(map, ir->branch_taken->pc));
240249
else {
241-
LLVMBasicBlockRef taken_entry = LLVMAppendBasicBlock(start,
242-
"taken_"
243-
"entry");
244-
LLVMBuilderRef taken_builder = LLVMCreateBuilder();
245-
LLVMPositionBuilderAtEnd(taken_builder, taken_entry);
246-
LLVMBuildBr(tk, taken_entry);
247-
t2c_trace_ebb(&taken_builder, param_types, start, &taken_entry,
248-
rv, ir->branch_taken, set, map);
250+
block_t *blk =
251+
cache_get(rv->block_cache, ir->branch_taken->pc, false);
252+
if (blk && blk->translatable
253+
#if RV32_HAS(SYSTEM)
254+
&& blk->satp == block->satp
255+
#endif
256+
) {
257+
LLVMBasicBlockRef taken_entry =
258+
LLVMAppendBasicBlock(start, "taken_entry");
259+
LLVMBuilderRef taken_builder = LLVMCreateBuilder();
260+
LLVMPositionBuilderAtEnd(taken_builder, taken_entry);
261+
LLVMBuildBr(tk, taken_entry);
262+
t2c_trace_ebb(&taken_builder, param_types, start,
263+
&taken_entry, rv, blk, set, map);
264+
}
249265
}
250266
}
251267
}
@@ -254,6 +270,9 @@ static void t2c_trace_ebb(LLVMBuilderRef *builder,
254270
void t2c_compile(riscv_t *rv, block_t *block)
255271
{
256272
LLVMModuleRef module = LLVMModuleCreateWithName("my_module");
273+
/* FIXME: riscv_t structure would change according to different
274+
* configuration. The linked block might jump to the wrong function pointer.
275+
*/
257276
LLVMTypeRef io_members[] = {
258277
LLVMPointerType(LLVMVoidType(), 0), LLVMPointerType(LLVMVoidType(), 0),
259278
LLVMPointerType(LLVMVoidType(), 0), LLVMPointerType(LLVMVoidType(), 0),
@@ -291,8 +310,7 @@ void t2c_compile(riscv_t *rv, block_t *block)
291310
struct LLVM_block_map map;
292311
map.count = 0;
293312
/* Translate custon IR into LLVM IR */
294-
t2c_trace_ebb(&builder, param_types, start, &entry, rv, block->ir_head,
295-
&set, &map);
313+
t2c_trace_ebb(&builder, param_types, start, &entry, rv, block, &set, &map);
296314
/* Offload LLVM IR to LLVM backend */
297315
char *error = NULL, *triple = LLVMGetDefaultTargetTriple();
298316
LLVMExecutionEngineRef engine;
@@ -319,7 +337,15 @@ void t2c_compile(riscv_t *rv, block_t *block)
319337

320338
/* Return the function pointer of T2C generated machine code */
321339
block->func = (exec_t2c_func_t) LLVMGetPointerToGlobal(engine, start);
322-
jit_cache_update(rv->jit_cache, block->pc_start, block->func);
340+
341+
#if RV32_HAS(SYSTEM)
342+
uint64_t key = (uint64_t) block->pc_start | ((uint64_t) block->satp << 32);
343+
#else
344+
uint64_t key = (uint64_t) block->pc_start;
345+
#endif
346+
347+
jit_cache_update(rv->jit_cache, key, block->func);
348+
323349
block->hot2 = true;
324350
}
325351

@@ -333,11 +359,11 @@ void jit_cache_exit(struct jit_cache *cache)
333359
free(cache);
334360
}
335361

336-
void jit_cache_update(struct jit_cache *cache, uint32_t pc, void *entry)
362+
void jit_cache_update(struct jit_cache *cache, uint64_t key, void *entry)
337363
{
338-
uint32_t pos = pc & (N_JIT_CACHE_ENTRIES - 1);
364+
uint32_t pos = key & (N_JIT_CACHE_ENTRIES - 1);
339365

340-
cache[pos].pc = pc;
366+
cache[pos].key = key;
341367
cache[pos].entry = entry;
342368
}
343369

0 commit comments

Comments
 (0)