Skip to content

Commit 6d0e0ef

Browse files
committed
Add profiling data log
1 parent b5a22d8 commit 6d0e0ef

File tree

8 files changed

+152
-20
lines changed

8 files changed

+152
-20
lines changed

src/cache.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <assert.h>
77
#include <stdbool.h>
88
#include <stddef.h>
9+
#include <stdio.h>
910
#include <stdlib.h>
1011
#include <string.h>
1112

@@ -274,4 +275,16 @@ bool cache_hot(const struct cache *cache, uint32_t key)
274275
}
275276
return false;
276277
}
278+
void cache_profile(const struct cache *cache,
279+
FILE *output_file,
280+
prof_func_t func)
281+
{
282+
assert(func);
283+
for (int i = 0; i < THRESHOLD; i++) {
284+
lfu_entry_t *entry, *safe;
285+
list_for_each_entry_safe (entry, safe, cache->lists[i], list) {
286+
func(entry->value, entry->frequency, output_file);
287+
}
288+
}
289+
}
277290
#endif

src/cache.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <stdbool.h>
99
#include <stdint.h>
10+
#include <stdio.h>
1011

1112
/* Currently, THRESHOLD is set to identify hot spots. Once the using frequency
1213
* for a block exceeds the THRESHOLD, the tier-1 JIT compiler process is
@@ -55,6 +56,11 @@ void cache_free(struct cache *cache);
5556
* @key: the key of the specified entry
5657
*/
5758
bool cache_hot(const struct cache *cache, uint32_t key);
59+
60+
typedef void (*prof_func_t)(void *, uint32_t, FILE *);
61+
void cache_profile(const struct cache *cache,
62+
FILE *output_file,
63+
prof_func_t func);
5864
#endif
5965

6066
uint32_t cache_freq(const struct cache *cache, uint32_t key);

src/emulate.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ static block_t *block_alloc(riscv_t *rv)
305305
block->translatable = true;
306306
block->hot = false;
307307
block->backward = false;
308-
block->loop = false;
308+
block->has_loops = false;
309309
INIT_LIST_HEAD(&block->list);
310310
#endif
311311
return block;
@@ -386,7 +386,7 @@ static uint32_t last_pc = 0;
386386

387387
#if RV32_HAS(JIT)
388388
static set_t pc_set;
389-
static bool loop = false;
389+
static bool has_loops = false;
390390
#endif
391391

392392
/* Interpreter-based execution path */
@@ -634,8 +634,10 @@ static void block_translate(riscv_t *rv, block_t *block)
634634
#endif
635635
/* stop on branch */
636636
if (insn_is_branch(ir->opcode)) {
637+
#if RV32_HAS(JIT)
637638
if (ir->imm < 0)
638639
block->backward = true;
640+
#endif
639641
if (ir->opcode == rv_insn_jalr
640642
#if RV32_HAS(EXT_C)
641643
|| ir->opcode == rv_insn_cjalr || ir->opcode == rv_insn_cjr
@@ -1054,10 +1056,10 @@ static bool runtime_profiler(riscv_t *rv, block_t *block)
10541056
uint32_t freq = cache_freq(rv->block_cache, block->pc_start);
10551057
/* to profile the block after chaining, the block should be executed first
10561058
*/
1057-
if (freq >= 2 && (block->backward || block->loop))
1059+
if (unlikely(freq >= 2 && (block->backward || block->has_loops)))
10581060
return true;
10591061
/* using frequency exceeds predetermined threshold */
1060-
if (freq == THRESHOLD)
1062+
if (unlikely(freq == THRESHOLD))
10611063
return true;
10621064
return false;
10631065
}
@@ -1148,7 +1150,7 @@ void rv_step(riscv_t *rv, int32_t cycles)
11481150
continue;
11491151
}
11501152
set_reset(&pc_set);
1151-
loop = false;
1153+
has_loops = false;
11521154
#endif
11531155
/* execute the block by interpreter */
11541156
const rv_insn_t *ir = block->ir_head;
@@ -1158,8 +1160,8 @@ void rv_step(riscv_t *rv, int32_t cycles)
11581160
break;
11591161
}
11601162
#if RV32_HAS(JIT)
1161-
if (loop && !block->loop)
1162-
block->loop = true;
1163+
if (has_loops && !block->has_loops)
1164+
block->has_loops = true;
11631165
#endif
11641166
prev = block;
11651167
}

src/main.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ static const char *opt_prog_name = "a.out";
3737
/* target argc and argv */
3838
static int prog_argc;
3939
static char **prog_args;
40-
static const char *optstr = "tgqmhd:a:";
40+
static const char *optstr = "tgqmhpd:a:";
4141

4242
/* enable misaligned memory access */
4343
static bool opt_misaligned = false;
4444

45+
/* dump profiling data */
46+
static bool opt_prof_data = false;
47+
static char *prof_out_file;
48+
4549
#define MEMIO(op) on_mem_##op
4650
#define IO_HANDLER_IMPL(type, op, RW) \
4751
static IIF(RW)( \
@@ -108,6 +112,7 @@ static void print_usage(const char *filename)
108112
" -a [filename] : dump signature to the given file, "
109113
"required by arch-test test\n"
110114
" -m : enable misaligned memory access\n"
115+
" -p : generate profiling data\n"
111116
" -h : show this message\n",
112117
filename);
113118
}
@@ -137,6 +142,9 @@ static bool parse_args(int argc, char **args)
137142
case 'm':
138143
opt_misaligned = true;
139144
break;
145+
case 'p':
146+
opt_prof_data = true;
147+
break;
140148
case 'd':
141149
opt_dump_regs = true;
142150
registers_out_file = optarg;
@@ -158,6 +166,12 @@ static bool parse_args(int argc, char **args)
158166
*/
159167
prog_args = &args[optind];
160168
opt_prog_name = prog_args[0];
169+
if (opt_prof_data) {
170+
char *prog_name = malloc(strlen(opt_prog_name) - 11);
171+
strncpy(prog_name, opt_prog_name + 8, strlen(opt_prog_name) - 12);
172+
prof_out_file = malloc(strlen(opt_prog_name) + 1);
173+
sprintf(prof_out_file, "./prof/%s.prof", prog_name);
174+
}
161175
return true;
162176
}
163177

@@ -264,6 +278,8 @@ int main(int argc, char **args)
264278
if (opt_arch_test)
265279
dump_test_signature(elf);
266280

281+
if (opt_prof_data)
282+
rv_profile(rv, prof_out_file);
267283
/* finalize the RISC-V runtime */
268284
elf_delete(elf);
269285
rv_delete(rv);

src/riscv.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,96 @@ void state_delete(state_t *s)
325325
memory_delete(s->mem);
326326
free(s);
327327
}
328+
329+
static const char *insn_name_table[] = {
330+
#define _(inst, can_branch, insn_len, translatable, reg_mask) \
331+
[rv_insn_##inst] = #inst,
332+
RV_INSN_LIST
333+
#undef _
334+
#define _(inst) [rv_insn_##inst] = #inst,
335+
FUSE_INSN_LIST
336+
#undef _
337+
};
338+
339+
#if RV32_HAS(JIT)
340+
void profile(block_t *block, uint32_t freq, FILE *output_file)
341+
{
342+
fprintf(output_file, "%#-9x|", block->pc_start);
343+
fprintf(output_file, "%#-8x|", block->pc_end);
344+
fprintf(output_file, " %-10u|", freq);
345+
fprintf(output_file, " %-5s |", block->hot ? "true" : "false");
346+
fprintf(output_file, " %-8s |", block->backward ? "true" : "false");
347+
fprintf(output_file, " %-6s |", block->has_loops ? "true" : "false");
348+
rv_insn_t *taken = block->ir_tail->branch_taken,
349+
*untaken = block->ir_tail->branch_untaken;
350+
if (untaken)
351+
fprintf(output_file, "%#-9x|", untaken->pc);
352+
else
353+
fprintf(output_file, "%-9s|", "NULL");
354+
if (taken)
355+
fprintf(output_file, "%#-8x|", taken->pc);
356+
else
357+
fprintf(output_file, "%-8s|", "NULL");
358+
rv_insn_t *ir = block->ir_head;
359+
while (1) {
360+
assert(ir);
361+
fprintf(output_file, "%s", insn_name_table[ir->opcode]);
362+
if (!ir->next)
363+
break;
364+
ir = ir->next;
365+
fprintf(output_file, " - ");
366+
}
367+
fprintf(output_file, "\n");
368+
}
369+
#endif
370+
371+
void rv_profile(riscv_t *rv, char *out_file_path)
372+
{
373+
if (!out_file_path) {
374+
fprintf(stderr, "Profiling data output file is NULL.\n");
375+
return;
376+
}
377+
FILE *f = fopen(out_file_path, "w");
378+
if (!f) {
379+
fprintf(stderr, "Cannot open profiling data output file.\n");
380+
return;
381+
}
382+
#if RV32_HAS(JIT)
383+
fprintf(f,
384+
"PC start |PC end | frequency | hot | backward | loop | "
385+
"untaken | taken "
386+
"| IR "
387+
"list \n");
388+
cache_profile(rv->block_cache, f, (prof_func_t) profile);
389+
#else
390+
fprintf(f, "PC start |PC end | untaken | taken | IR list \n");
391+
block_map_t *map = &rv->block_map;
392+
for (uint32_t i = 0; i < map->block_capacity; i++) {
393+
block_t *block = map->map[i];
394+
if (!block)
395+
continue;
396+
fprintf(f, "%#-9x|", block->pc_start);
397+
fprintf(f, "%#-8x|", block->pc_end);
398+
rv_insn_t *taken = block->ir_tail->branch_taken,
399+
*untaken = block->ir_tail->branch_untaken;
400+
if (untaken)
401+
fprintf(f, "%#-9x|", untaken->pc);
402+
else
403+
fprintf(f, "%-9s|", "NULL");
404+
if (taken)
405+
fprintf(f, "%#-8x|", taken->pc);
406+
else
407+
fprintf(f, "%-8s|", "NULL");
408+
rv_insn_t *ir = block->ir_head;
409+
while (1) {
410+
assert(ir);
411+
fprintf(f, "%s", insn_name_table[ir->opcode]);
412+
if (!ir->next)
413+
break;
414+
ir = ir->next;
415+
fprintf(f, " - ");
416+
}
417+
fprintf(f, "\n");
418+
}
419+
#endif
420+
}

src/riscv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ state_t *state_new(void);
227227
/* delete a state */
228228
void state_delete(state_t *s);
229229

230+
void rv_profile(riscv_t *rv, char *out_file_path);
231+
230232
#ifdef __cplusplus
231233
};
232234
#endif

src/riscv_private.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ typedef struct block {
6262
uint32_t pc_start, pc_end; /**< address range of the basic block */
6363

6464
rv_insn_t *ir_head, *ir_tail; /**< the first and last ir for this block */
65-
bool backward;
6665
#if RV32_HAS(JIT)
67-
bool hot; /**< Determine the block is hotspot or not */
66+
bool backward; /**< Determine the block has backward jump or not */
67+
bool hot; /**< Determine the block is hotspot or not */
6868
uint32_t offset;
6969
bool
7070
translatable; /**< Determine the block has RV32AF insturctions or not */
71-
bool loop; /**< Determine the block has loop or not */
71+
bool has_loops; /**< Determine the block has loop or not */
7272
struct list_head list;
7373
#endif
7474
} block_t;

src/rv32_template.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ RVOP(
150150
#if RV32_HAS(JIT)
151151
cache_get(rv->block_cache, PC, true);
152152
if (!set_add(&pc_set, PC))
153-
loop = true;
153+
has_loops = true;
154154
if (cache_hot(rv->block_cache, PC))
155155
goto end_insn;
156156
#endif
@@ -251,7 +251,7 @@ RVOP(
251251
({ \
252252
cache_get(rv->block_cache, PC + 4, true); \
253253
if (!set_add(&pc_set, PC + 4)) \
254-
loop = true; \
254+
has_loops = true; \
255255
if (cache_hot(rv->block_cache, PC + 4)) \
256256
goto nextop; \
257257
}, ); \
@@ -270,7 +270,7 @@ RVOP(
270270
({ \
271271
cache_get(rv->block_cache, PC, true); \
272272
if (!set_add(&pc_set, PC)) \
273-
loop = true; \
273+
has_loops = true; \
274274
if (cache_hot(rv->block_cache, PC)) \
275275
goto end_insn; \
276276
}, ); \
@@ -1857,7 +1857,7 @@ RVOP(
18571857
#if RV32_HAS(JIT)
18581858
cache_get(rv->block_cache, PC, true);
18591859
if (!set_add(&pc_set, PC))
1860-
loop = true;
1860+
has_loops = true;
18611861
if (cache_hot(rv->block_cache, PC))
18621862
goto end_insn;
18631863
#endif
@@ -2020,7 +2020,7 @@ RVOP(
20202020
#if RV32_HAS(JIT)
20212021
cache_get(rv->block_cache, PC, true);
20222022
if (!set_add(&pc_set, PC))
2023-
loop = true;
2023+
has_loops = true;
20242024
if (cache_hot(rv->block_cache, PC))
20252025
goto end_insn;
20262026
#endif
@@ -2055,7 +2055,7 @@ RVOP(
20552055
#if RV32_HAS(JIT)
20562056
cache_get(rv->block_cache, PC + 2, true);
20572057
if (!set_add(&pc_set, PC + 2))
2058-
loop = true;
2058+
has_loops = true;
20592059
if (cache_hot(rv->block_cache, PC + 2))
20602060
goto nextop;
20612061
#endif
@@ -2070,7 +2070,7 @@ RVOP(
20702070
#if RV32_HAS(JIT)
20712071
cache_get(rv->block_cache, PC, true);
20722072
if (!set_add(&pc_set, PC))
2073-
loop = true;
2073+
has_loops = true;
20742074
if (cache_hot(rv->block_cache, PC))
20752075
goto end_insn;
20762076
#endif
@@ -2114,7 +2114,7 @@ RVOP(
21142114
#if RV32_HAS(JIT)
21152115
cache_get(rv->block_cache, PC + 2, true);
21162116
if (!set_add(&pc_set, PC + 2))
2117-
loop = true;
2117+
has_loops = true;
21182118
if (cache_hot(rv->block_cache, PC + 2))
21192119
goto nextop;
21202120
#endif
@@ -2129,7 +2129,7 @@ RVOP(
21292129
#if RV32_HAS(JIT)
21302130
cache_get(rv->block_cache, PC, true);
21312131
if (!set_add(&pc_set, PC))
2132-
loop = true;
2132+
has_loops = true;
21332133
if (cache_hot(rv->block_cache, PC))
21342134
goto end_insn;
21352135
#endif

0 commit comments

Comments
 (0)