cavatools: initialize repository
[cavatools.git] / pipesim / cache.h
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5
6 #ifndef CACHE_T
7 #define CACHE_T
8
9
10 struct tag_t { /* 16 byte object */
11 long addr ; /* 64-bit entry */
12 unsigned dirty : 1; /* 1 bit flag */
13 long ready : 63; /* 63 bit time */
14 };
15
16 struct lru_fsm_t {
17 unsigned short way; /* cache way to look up */
18 unsigned short next_state; /* number if hit */
19 };
20
21 struct cache_t { /* cache descriptor */
22 struct lru_fsm_t* fsm; /* LRU state transitions [ways!][ways] */
23 long line; /* line size in bytes */
24 long rows; /* number of rows */
25 long ways; /* number of ways */
26 long lg_line, lg_rows; /* specified in log-base-2 units */
27 long row_mask; /* row index mask = (1<<lg_rows)-1 */
28 struct tag_t** tags; /* cache tag array [ways]->[rows] */
29 unsigned short* states; /* LRU state vector [rows] */
30 long* evicted; /* tag of evicted line, 0 if clean, NULL if unwritable */
31 long penalty; /* cycles to refill line */
32 long refs, misses; /* count number of */
33 long updates, evictions; /* if writeable */
34 };
35
36 void flush_cache( struct cache_t* c );
37
38 void init_cache( struct cache_t* c, struct lru_fsm_t* fsm, int writeable );
39
40 void show_cache( struct cache_t* c );
41
42
43 /* returns cycle when line available (may be in past)
44 cache miss if return value == when_miss_arrive */
45 static inline long lookup_cache( struct cache_t* c, long addr, int write, long when_miss_arrive )
46 {
47 c->refs++;
48 addr >>= c->lg_line; /* make proper tag (ok to include index) */
49 int index = addr & c->row_mask;
50 unsigned short* state = c->states + index;
51
52 struct lru_fsm_t* p = c->fsm + *state; /* recall c->fsm points to [-1] */
53 struct lru_fsm_t* end = p + c->ways; /* hence +ways = last entry */
54 struct tag_t* tag;
55 do {
56 p++;
57 tag = c->tags[p->way] + index;
58 if (addr == tag->addr)
59 goto cache_hit;
60 } while (p < end);
61
62 c->misses++;
63 if (tag->dirty) {
64 *c->evicted = tag->addr; /* will SEGV if not cache not writable */
65 c->evictions++; /* can conveniently point to your location */
66 tag->dirty = 0;
67 }
68 else if (c->evicted)
69 *c->evicted = 0;
70 tag->addr = addr;
71 tag->ready = when_miss_arrive;
72
73 cache_hit:
74 *state = p->next_state; /* already multiplied by c->ways */
75 if (write) {
76 tag->dirty = 1;
77 c->updates++;
78 }
79 return tag->ready;
80 }
81
82
83
84 #endif