diff options
Diffstat (limited to 'demo')
| -rw-r--r-- | demo/cache.c | 82 | ||||
| -rw-r--r-- | demo/console.c | 3 | ||||
| -rw-r--r-- | demo/demo.h | 7 | ||||
| -rw-r--r-- | demo/main.c | 25 | ||||
| -rw-r--r-- | demo/util.c | 31 |
5 files changed, 135 insertions, 13 deletions
diff --git a/demo/cache.c b/demo/cache.c new file mode 100644 index 0000000..d2a22cd --- /dev/null +++ b/demo/cache.c @@ -0,0 +1,82 @@ +#include "demo.h" + +#define CACHE_DEBUG_BASE(n) (0x30100000 | (0x10000 * (n))) +#define CACHE_DEBUG_WORD(n, i) (*(volatile unsigned *)(CACHE_DEBUG_BASE(n) + 16 + 4 * (i))) + +#define CACHE_STATUS(n) (*(volatile unsigned *)CACHE_DEBUG_BASE(n)) +#define CACHE_STATUS_CACHED (1 << 1) +#define CACHE_STATUS_STATE_MASK 0x0000000c +#define CACHE_STATUS_STATE_SHIFT 2 +#define CACHE_STATUS_INDEX_MASK 0x00001ff0 +#define CACHE_STATUS_INDEX_SHIFT 4 +#define CACHE_STATUS_INDEX_BITS 9 +#define CACHE_STATUS_TAG_MASK 0x1fffe000 +#define CACHE_STATUS_TAG_SHIFT 13 +#define CACHE_STATUS_TAG_BITS 16 +#define CACHE_STATUS_STATE_I 0b00 +#define CACHE_STATUS_STATE_S 0b01 +#define CACHE_STATUS_STATE_E 0b10 +#define CACHE_STATUS_STATE_M 0b11 + +void cache_debug(unsigned cpu, void *ptr) +{ + unsigned ptr_val = (unsigned)ptr; + + CACHE_STATUS(cpu) = (unsigned)ptr; + unsigned status = CACHE_STATUS(cpu); + + int cached = status & CACHE_STATUS_CACHED; + + print("req_addr: %p", ptr); + print("cacheability: %s", cached ? "write-back" : "uncached (I/O)"); + + if (!cached) + return; + + unsigned index = (status & CACHE_STATUS_INDEX_MASK) >> CACHE_STATUS_INDEX_SHIFT; + unsigned addr_tag = (ptr_val & CACHE_STATUS_TAG_MASK) >> CACHE_STATUS_TAG_SHIFT; + unsigned cache_tag = (status & CACHE_STATUS_TAG_MASK) >> CACHE_STATUS_TAG_SHIFT; + unsigned line_addr = status & (CACHE_STATUS_TAG_MASK | CACHE_STATUS_INDEX_MASK); + + print("index: %r", index, CACHE_STATUS_INDEX_BITS); + print("req_tag: %r", addr_tag, CACHE_STATUS_TAG_BITS); + print("cache_tag: %r", cache_tag, CACHE_STATUS_TAG_BITS); + print("req_line: %p", ptr_val & (CACHE_STATUS_TAG_MASK | CACHE_STATUS_INDEX_MASK)); + print("cache_line: %p", line_addr); + + int valid, dirty; + const char *state; + + switch ((status & CACHE_STATUS_STATE_MASK) >> CACHE_STATUS_STATE_SHIFT) { + case CACHE_STATUS_STATE_I: + valid = 0; + dirty = 0; + state = "INVALID"; + break; + + case CACHE_STATUS_STATE_S: + valid = 1; + dirty = 0; + state = "SHARED"; + break; + + case CACHE_STATUS_STATE_E: + valid = 1; + dirty = 0; + state = "EXCLUSIVE"; + break; + + case CACHE_STATUS_STATE_M: + valid = 1; + dirty = 1; + state = "MODIFIED"; + break; + } + + print("valid=%d dirty=%d state=%s", valid, dirty, state); + print("access is a %s on cpu%u", valid && addr_tag == cache_tag ? "hit" : "miss", cpu); + + for (unsigned i = 0; i < 4; ++i) { + print("%p: %x", line_addr | i << CACHE_STATUS_STATE_SHIFT, CACHE_DEBUG_WORD(cpu, i)); + } +} diff --git a/demo/console.c b/demo/console.c index b35ace7..d2d13fa 100644 --- a/demo/console.c +++ b/demo/console.c @@ -48,7 +48,8 @@ static void print_hex(unsigned val, unsigned bits) if (bits > 32) bits = 32; - bits = bits & ~3; + bits = (bits + 3) & ~3; + do print_char(hex_digits[(val >> (bits -= 4)) & 0xf]); while (bits); diff --git a/demo/demo.h b/demo/demo.h index a8d81ce..ca6199e 100644 --- a/demo/demo.h +++ b/demo/demo.h @@ -35,10 +35,15 @@ void halt_cpus(unsigned mask); int strcmp(const char *s1, const char *s2); char *strtok_input(char **tokens); +int expect_end(char **tokens); + int parse_hex(char **tokens, unsigned *val); int parse_ptr(char **tokens, void **ptr); int parse_aligned(char **tokens, void **ptr); + +int parse_cpu(char **tokens, unsigned *cpu); int parse_cpu_mask(char **tokens, unsigned *mask); -int expect_end(char **tokens); + +void cache_debug(unsigned cpu, void *ptr); #endif diff --git a/demo/main.c b/demo/main.c index fe17ec2..10067d2 100644 --- a/demo/main.c +++ b/demo/main.c @@ -22,7 +22,7 @@ static void cmd_halt(char **tokens) halt_cpus(mask); } -static void cmd_rd(char **tokens) +static void cmd_read(char **tokens) { void *ptr; if (parse_aligned(tokens, &ptr) < 0 || expect_end(tokens) < 0) @@ -31,7 +31,7 @@ static void cmd_rd(char **tokens) print("%p: %x", ptr, *(volatile unsigned *)ptr); } -static void cmd_wr(char **tokens) +static void cmd_write(char **tokens) { void *ptr; unsigned val; @@ -42,6 +42,17 @@ static void cmd_wr(char **tokens) *(volatile unsigned *)ptr = val; } +static void cmd_cache(char **tokens) +{ + void *ptr; + unsigned cpu; + + if (parse_cpu(tokens, &cpu) < 0 || parse_ptr(tokens, &ptr) < 0) + return; + + cache_debug(cpu, ptr); +} + void bsp_main(void) { run_cpu(1); @@ -63,10 +74,12 @@ void bsp_main(void) cmd_run(&tokens); else if (!strcmp(cmd, "halt")) cmd_halt(&tokens); - else if (!strcmp(cmd, "rd")) - cmd_rd(&tokens); - else if (!strcmp(cmd, "wr")) - cmd_wr(&tokens); + else if (!strcmp(cmd, "read")) + cmd_read(&tokens); + else if (!strcmp(cmd, "write")) + cmd_write(&tokens); + else if (!strcmp(cmd, "cache")) + cmd_cache(&tokens); else print("unknown command '%s'", cmd); } diff --git a/demo/util.c b/demo/util.c index b0ef3cb..d08ec20 100644 --- a/demo/util.c +++ b/demo/util.c @@ -12,6 +12,18 @@ 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' + || !('0' <= token[3] && token[3] < '0' + NUM_CPUS) || token[4]) { + bad_input(); + return -1; + } + + *cpu = token[3] - '0'; + return 0; +} + int strcmp(const char *s1, const char *s2) { while (*s1 && *s1 == *s2) @@ -41,19 +53,28 @@ char *strtok_input(char **tokens) return start; } +int parse_cpu(char **tokens, unsigned *cpu) +{ + char *token = strtok_input(tokens); + if (!token) { + unexpected_eof(); + return -1; + } + + return parse_cpu_token(token, cpu); +} + int parse_cpu_mask(char **tokens, unsigned *mask) { *mask = 0; char *token; while ((token = strtok_input(tokens))) { - if (token[0] != 'c' || token[1] != 'p' || token[2] != 'u' - || !('0' <= token[3] && token[3] < '0' + NUM_CPUS) || token[4]) { - bad_input(); + unsigned cpu; + if (parse_cpu_token(token, &cpu) < 0) return -1; - } - *mask |= 1 << (token[3] - '0'); + *mask |= 1 << cpu; } if (!*mask) { |
