summaryrefslogtreecommitdiff
path: root/demo
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2023-10-04 03:46:29 -0600
committerAlejandro Soto <alejandro@34project.org>2023-10-04 05:04:04 -0600
commitf52299cf837951cbc1dc92fd0d084444ac3dc712 (patch)
tree81db03717f1571d0e1e75f8de8d7915a0c7cb084 /demo
parent3de2c7e7dd214f80b8b9cca575e42e0b1b08034d (diff)
demo: implement cache debug
Diffstat (limited to '')
-rw-r--r--demo/cache.c82
-rw-r--r--demo/console.c3
-rw-r--r--demo/demo.h7
-rw-r--r--demo/main.c25
-rw-r--r--demo/util.c31
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) {