diff options
| author | Alejandro Soto <alejandro@34project.org> | 2023-10-05 17:18:56 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2023-10-05 17:18:56 -0600 |
| commit | cf32fe6cf81040e04036f0fcf72f814ab891bb8a (patch) | |
| tree | a1e1c50ab905ce6b7b85dcffc98c09995d72e693 /demo | |
| parent | d406720cecd7328f595255e65b6fd6b6814cefe4 (diff) | |
demo: implement perf command
Diffstat (limited to 'demo')
| -rw-r--r-- | demo/demo.h | 4 | ||||
| -rw-r--r-- | demo/main.c | 30 | ||||
| -rw-r--r-- | demo/perf.c | 60 | ||||
| -rw-r--r-- | demo/util.c | 10 |
4 files changed, 98 insertions, 6 deletions
diff --git a/demo/demo.h b/demo/demo.h index f98d599..c889e1a 100644 --- a/demo/demo.h +++ b/demo/demo.h @@ -35,6 +35,7 @@ int strcmp(const char *s1, const char *s2); char *strtok_input(char **tokens); int expect_end(char **tokens); +void unexpected_eof(); int parse_hex(char **tokens, unsigned *val); int parse_ptr(char **tokens, void **ptr); @@ -45,4 +46,7 @@ int parse_cpu_mask(char **tokens, unsigned *mask); void cache_debug(unsigned cpu, void *ptr); +void perf_show(unsigned cpu); +void perf_clear(unsigned cpu); + #endif diff --git a/demo/main.c b/demo/main.c index 988ef55..89347ad 100644 --- a/demo/main.c +++ b/demo/main.c @@ -6,6 +6,11 @@ struct cpu *__cpus[] = { &cpu0, &cpu1, &cpu2, &cpu3 }; static volatile unsigned boot_done; +static void unknown_command(const char *cmd) +{ + print("unknown command '%s'", cmd); +} + static void cmd_run(char **tokens) { unsigned mask; @@ -55,6 +60,27 @@ static void cmd_cache(char **tokens) cache_debug(cpu, ptr); } +static void cmd_perf(char **tokens) +{ + unsigned cpu; + const char *cmd; + + if (parse_cpu(tokens, &cpu) < 0) + return; + else if (!(cmd = strtok_input(tokens))) { + unexpected_eof(); + return; + } else if (expect_end(tokens) < 0) + return; + + if (!strcmp(cmd, "clear")) + perf_clear(cpu); + else if (!strcmp(cmd, "show")) + perf_show(cpu); + else + unknown_command(cmd); +} + static void bsp_main(void) { boot_done = 0; @@ -83,8 +109,10 @@ static void bsp_main(void) cmd_write(&tokens); else if (!strcmp(cmd, "cache")) cmd_cache(&tokens); + else if (!strcmp(cmd, "perf")) + cmd_perf(&tokens); else - print("unknown command '%s'", cmd); + unknown_command(cmd); } } diff --git a/demo/perf.c b/demo/perf.c new file mode 100644 index 0000000..28a20c8 --- /dev/null +++ b/demo/perf.c @@ -0,0 +1,60 @@ +#include "demo.h" + +#define PERF_BASE(n) (0x30150000 | (0x40 * (n))) +#define PERF_CLEAR(n) (*(volatile unsigned *)PERF_BASE(n)) +#define PERF_MEM_READS(n) (*(const volatile unsigned *)PERF_BASE(n)) +#define PERF_MEM_WRITES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 4)) +#define PERF_MEM_READ_CYCLES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 8)) +#define PERF_MEM_WRITE_CYCLES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 12)) +#define PERF_RING_READS(n) (*(const volatile unsigned *)(PERF_BASE(n) + 16)) +#define PERF_RING_INVALS(n) (*(const volatile unsigned *)(PERF_BASE(n) + 20)) +#define PERF_RING_READ_INVALS(n) (*(const volatile unsigned *)(PERF_BASE(n) + 24)) +#define PERF_RING_REPLIES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 28)) +#define PERF_RING_FORWARDS(n) (*(const volatile unsigned *)(PERF_BASE(n) + 32)) +#define PERF_RING_CYCLES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 36)) +#define PERF_IO_READS(n) (*(const volatile unsigned *)(PERF_BASE(n) + 40)) +#define PERF_IO_WRITES(n) (*(const volatile unsigned *)(PERF_BASE(n) + 44)) + +#define PERF_MIN_MASK 0x0000ffff +#define PERF_MAX_MASK 0xffff0000 +#define PERF_MAX_SHIFT 16 + +void perf_show(unsigned cpu) +{ + print("dumping performance counters for cpu%u", cpu); + + unsigned mem_reads = PERF_MEM_READS(cpu); + unsigned mem_writes = PERF_MEM_WRITES(cpu); + unsigned read_cycles = PERF_MEM_READ_CYCLES(cpu); + unsigned write_cycles = PERF_MEM_WRITE_CYCLES(cpu); + unsigned ring_reads = PERF_RING_READS(cpu); + unsigned ring_invals = PERF_RING_INVALS(cpu); + unsigned ring_read_invals = PERF_RING_READ_INVALS(cpu); + unsigned ring_replies = PERF_RING_REPLIES(cpu); + unsigned ring_forwards = PERF_RING_FORWARDS(cpu); + unsigned ring_cycles = PERF_RING_CYCLES(cpu); + unsigned io_reads = PERF_IO_READS(cpu); + unsigned io_writes = PERF_IO_WRITES(cpu); + + unsigned min_ring_cycles = ring_cycles & PERF_MIN_MASK; + unsigned max_ring_cycles = (ring_cycles & PERF_MAX_MASK) >> PERF_MAX_SHIFT; + unsigned min_read_cycles = read_cycles & PERF_MIN_MASK; + unsigned max_read_cycles = (read_cycles & PERF_MAX_MASK) >> PERF_MAX_SHIFT; + unsigned min_write_cycles = write_cycles & PERF_MIN_MASK; + unsigned max_write_cycles = (write_cycles & PERF_MAX_MASK) >> PERF_MAX_SHIFT; + unsigned ring_sends = ring_reads + ring_invals + ring_read_invals; + + print("requests: sends=%u forwards=%u replies=%u", ring_sends, ring_forwards, ring_replies); + print("requests sent: read=%u inval=%u read_inval=%u", ring_reads, ring_invals, ring_read_invals); + print("memory: misses=%u writebacks=%u", mem_reads, mem_writes); + print("uncached i/o: reads=%u writes=%u", io_reads, io_writes); + print("ring cycles: min=%u max=%u", min_ring_cycles, max_ring_cycles); + print("mem read cycles: min=%u max=%u", min_read_cycles, max_read_cycles); + print("mem write cycles: min=%u max=%u", min_write_cycles, max_write_cycles); +} + +void perf_clear(unsigned cpu) +{ + PERF_CLEAR(cpu) = 0; + print("cleared performance counters for cpu%u", cpu); +} diff --git a/demo/util.c b/demo/util.c index d08ec20..d728fac 100644 --- a/demo/util.c +++ b/demo/util.c @@ -7,11 +7,6 @@ static void bad_input(void) print("bad input"); } -static void unexpected_eof(void) -{ - print("unexpected end-of-input"); -} - static int parse_cpu_token(const char *token, unsigned *cpu) { if (token[0] != 'c' || token[1] != 'p' || token[2] != 'u' @@ -24,6 +19,11 @@ static int parse_cpu_token(const char *token, unsigned *cpu) return 0; } +void unexpected_eof(void) +{ + print("unexpected end-of-input"); +} + int strcmp(const char *s1, const char *s2) { while (*s1 && *s1 == *s2) |
