1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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));
}
}
|