diff options
Diffstat (limited to 'demo/cache.c')
| -rw-r--r-- | demo/cache.c | 82 |
1 files changed, 82 insertions, 0 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)); + } +} |
