Skip to content

Commit dedc042

Browse files
committed
add TLB cache
1 parent fe11344 commit dedc042

File tree

3 files changed

+190
-53
lines changed

3 files changed

+190
-53
lines changed

src/hardware/cpu/mmu.c

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,151 @@
1717
#include "headers/common.h"
1818
#include "headers/address.h"
1919

20+
// -------------------------------------------- //
21+
// TLB cache struct
22+
// -------------------------------------------- //
23+
24+
#define NUM_TLB_CACHE_LINE_PER_SET (8)
25+
26+
typedef struct
27+
{
28+
int valid;
29+
uint64_t tag;
30+
uint64_t ppn;
31+
} tlb_cacheline_t;
32+
33+
typedef struct
34+
{
35+
tlb_cacheline_t lines[NUM_TLB_CACHE_LINE_PER_SET];
36+
} tlb_cacheset_t;
37+
38+
typedef struct
39+
{
40+
tlb_cacheset_t sets[(1 << TLB_CACHE_INDEX_LENGTH)];
41+
} tlb_cache_t;
42+
43+
static tlb_cache_t mmu_tlb;
44+
2045
static uint64_t page_walk(uint64_t vaddr_value);
2146
static void page_fault_handler(pte4_t *pte, address_t vaddr);
2247

48+
static int read_tlb(uint64_t vaddr_value, uint64_t *paddr_value_ptr,
49+
int *free_tlb_line_index);
50+
static int write_tlb(uint64_t vaddr_value, uint64_t paddr_value,
51+
int free_tlb_line_index);
52+
2353
int swap_in(uint64_t daddr, uint64_t ppn);
2454
int swap_out(uint64_t daddr, uint64_t ppn);
2555

2656
// consider this function va2pa as functional
2757
uint64_t va2pa(uint64_t vaddr)
2858
{
59+
uint64_t paddr = 0;
60+
61+
#ifdef USE_TLB_HARDWARE
62+
int free_tlb_line_index = -1;
63+
int tlb_hit = read_tlb(vaddr, &paddr, &free_tlb_line_index);
64+
65+
// TODO: add flag to read tlb failed
66+
if (tlb_hit)
67+
{
68+
// TLB read hit
69+
return paddr;
70+
}
71+
72+
// TLB read miss
73+
#endif
74+
75+
// assume that page_walk is consuming much time
76+
paddr = page_walk(vaddr);
77+
78+
#ifdef USE_TLB_HARDWARE
79+
// refresh TLB
80+
// TODO: check if this paddr from page table is a legal address
81+
if (paddr != 0)
82+
{
83+
// TLB write
84+
if (write_tlb(vaddr, paddr, free_tlb_line_index) == 1)
85+
{
86+
return paddr;
87+
}
88+
}
89+
#endif
90+
2991
// use page table as va2pa
30-
return page_walk(vaddr);
92+
return paddr;
93+
}
94+
95+
static int read_tlb(uint64_t vaddr_value, uint64_t *paddr_value_ptr,
96+
int *free_tlb_line_index)
97+
{
98+
address_t vaddr = {
99+
.address_value = vaddr_value
100+
};
101+
102+
tlb_cacheset_t *set = &mmu_tlb.sets[vaddr.tlbi];
103+
*free_tlb_line_index = -1;
104+
105+
for (int i = 0; i < NUM_TLB_CACHE_LINE_PER_SET; ++ i)
106+
{
107+
tlb_cacheline_t *line = &set->lines[i];
108+
109+
if (line->valid == 0)
110+
{
111+
*free_tlb_line_index = i;
112+
}
113+
114+
if (line->tag == vaddr.tlbt &&
115+
line->valid == 1)
116+
{
117+
// TLB read hit
118+
*paddr_value_ptr = line->ppn;
119+
return 1;
120+
}
121+
}
122+
123+
// TLB read miss
124+
*paddr_value_ptr = NULL;
125+
return 0;
31126
}
32127

128+
static int write_tlb(uint64_t vaddr_value, uint64_t paddr_value,
129+
int free_tlb_line_index)
130+
{
131+
address_t vaddr = {
132+
.address_value = vaddr_value
133+
};
134+
135+
address_t paddr = {
136+
.address_value = paddr_value
137+
};
138+
139+
tlb_cacheset_t *set = &mmu_tlb.sets[vaddr.tlbi];
140+
141+
if (0 <= free_tlb_line_index && free_tlb_line_index < NUM_TLB_CACHE_LINE_PER_SET)
142+
{
143+
tlb_cacheline_t *line = &set->lines[free_tlb_line_index];
144+
145+
line->valid = 1;
146+
line->ppn = paddr.ppn;
147+
line->tag = vaddr.tlbt;
148+
149+
return 1;
150+
}
151+
152+
// no free TLB cache line, select one RANDOM victim
153+
int random_victim_index = random() % NUM_TLB_CACHE_LINE_PER_SET;
154+
155+
tlb_cacheline_t *line = &set->lines[random_victim_index];
156+
157+
line->valid = 1;
158+
line->ppn = paddr.ppn;
159+
line->tag = vaddr.tlbt;
160+
161+
return 1;
162+
}
163+
164+
33165
// input - virtual address
34166
// output - physical address
35167
static uint64_t page_walk(uint64_t vaddr_value)

src/hardware/memory/dram.c

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -28,61 +28,55 @@ e.g. write 0x00007fd357a02ae0 to cache, the memory lapping should be:
2828
// memory accessing used in instructions
2929
uint64_t cpu_read64bits_dram(uint64_t paddr)
3030
{
31-
if (DEBUG_ENABLE_SRAM_CACHE == 1)
31+
#ifdef DEBUG_ENABLE_SRAM_CACHE
32+
// try to load uint64_t from SRAM cache
33+
// little-endian
34+
uint64_t val = 0x0;
35+
for (int i = 0; i < 8; ++ i)
3236
{
33-
// try to load uint64_t from SRAM cache
34-
// little-endian
35-
uint64_t val = 0x0;
36-
for (int i = 0; i < 8; ++ i)
37-
{
38-
val += (sram_cache_read(paddr + i) << (i * 8));
39-
}
40-
return val;
41-
}
42-
else
43-
{
44-
// read from DRAM directly
45-
// little-endian
46-
uint64_t val = 0x0;
47-
48-
val += (((uint64_t)pm[paddr + 0 ]) << 0);
49-
val += (((uint64_t)pm[paddr + 1 ]) << 8);
50-
val += (((uint64_t)pm[paddr + 2 ]) << 16);
51-
val += (((uint64_t)pm[paddr + 3 ]) << 24);
52-
val += (((uint64_t)pm[paddr + 4 ]) << 32);
53-
val += (((uint64_t)pm[paddr + 5 ]) << 40);
54-
val += (((uint64_t)pm[paddr + 6 ]) << 48);
55-
val += (((uint64_t)pm[paddr + 7 ]) << 56);
56-
57-
return val;
37+
val += (sram_cache_read(paddr + i) << (i * 8));
5838
}
39+
return val;
40+
#elif
41+
// read from DRAM directly
42+
// little-endian
43+
uint64_t val = 0x0;
44+
45+
val += (((uint64_t)pm[paddr + 0 ]) << 0);
46+
val += (((uint64_t)pm[paddr + 1 ]) << 8);
47+
val += (((uint64_t)pm[paddr + 2 ]) << 16);
48+
val += (((uint64_t)pm[paddr + 3 ]) << 24);
49+
val += (((uint64_t)pm[paddr + 4 ]) << 32);
50+
val += (((uint64_t)pm[paddr + 5 ]) << 40);
51+
val += (((uint64_t)pm[paddr + 6 ]) << 48);
52+
val += (((uint64_t)pm[paddr + 7 ]) << 56);
53+
54+
return val;
55+
#endif
5956
}
6057

6158
void cpu_write64bits_dram(uint64_t paddr, uint64_t data)
6259
{
63-
if (DEBUG_ENABLE_SRAM_CACHE == 1)
64-
{
65-
// try to write uint64_t to SRAM cache
66-
// little-endian
67-
for (int i = 0; i < 8; ++ i)
68-
{
69-
sram_cache_write(paddr + i, (data >> (i * 8)) & 0xff);
70-
}
71-
return;
72-
}
73-
else
60+
#ifdef DEBUG_ENABLE_SRAM_CACHE
61+
// try to write uint64_t to SRAM cache
62+
// little-endian
63+
for (int i = 0; i < 8; ++ i)
7464
{
75-
// write to DRAM directly
76-
// little-endian
77-
pm[paddr + 0] = (data >> 0 ) & 0xff;
78-
pm[paddr + 1] = (data >> 8 ) & 0xff;
79-
pm[paddr + 2] = (data >> 16) & 0xff;
80-
pm[paddr + 3] = (data >> 24) & 0xff;
81-
pm[paddr + 4] = (data >> 32) & 0xff;
82-
pm[paddr + 5] = (data >> 40) & 0xff;
83-
pm[paddr + 6] = (data >> 48) & 0xff;
84-
pm[paddr + 7] = (data >> 56) & 0xff;
65+
sram_cache_write(paddr + i, (data >> (i * 8)) & 0xff);
8566
}
67+
return;
68+
#elif
69+
// write to DRAM directly
70+
// little-endian
71+
pm[paddr + 0] = (data >> 0 ) & 0xff;
72+
pm[paddr + 1] = (data >> 8 ) & 0xff;
73+
pm[paddr + 2] = (data >> 16) & 0xff;
74+
pm[paddr + 3] = (data >> 24) & 0xff;
75+
pm[paddr + 4] = (data >> 32) & 0xff;
76+
pm[paddr + 5] = (data >> 40) & 0xff;
77+
pm[paddr + 6] = (data >> 48) & 0xff;
78+
pm[paddr + 7] = (data >> 56) & 0xff;
79+
#endif
8680
}
8781

8882
void cpu_readinst_dram(uint64_t paddr, char *buf)

src/headers/address.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232
#define VIRTUAL_PAGE_NUMBER_LENGTH (9) // 9 + 9 + 9 + 9 = 36
3333
#define VIRTUAL_ADDRESS_LENGTH (48)
3434

35+
#define TLB_CACHE_OFFSET_LENGTH (12)
36+
#define TLB_CACHE_INDEX_LENGTH (4)
37+
#define TLB_CACHE_TAG_LENGTH (32)
3538

3639
/*
3740
+--------+--------+--------+--------+---------------+
38-
| VPN3 | VPN2 | VPN1 | VPN0 | |
41+
| VPN1 | VPN2 | VPN3 | VPN4 | |
3942
+--------+--------+--------+-+------+ VPO |
4043
| TLBT | TLBI | |
4144
+---------------+------------+------+---------------+
@@ -62,6 +65,14 @@ typedef union
6265
};
6366
};
6467

68+
// sram cache: 52
69+
struct
70+
{
71+
uint64_t co : SRAM_CACHE_OFFSET_LENGTH;
72+
uint64_t ci : SRAM_CACHE_INDEX_LENGTH;
73+
uint64_t ct : SRAM_CACHE_TAG_LENGTH;
74+
};
75+
6576
// virtual address: 48
6677
struct
6778
{
@@ -79,12 +90,12 @@ typedef union
7990
};
8091
};
8192

82-
// sram cache: 52
93+
// TLB cache: 48
8394
struct
8495
{
85-
uint64_t co : SRAM_CACHE_OFFSET_LENGTH;
86-
uint64_t ci : SRAM_CACHE_INDEX_LENGTH;
87-
uint64_t ct : SRAM_CACHE_TAG_LENGTH;
96+
uint64_t tlbo : TLB_CACHE_OFFSET_LENGTH; // virtual page offset
97+
uint64_t tlbi : TLB_CACHE_INDEX_LENGTH; // TLB set index
98+
uint64_t tlbt : TLB_CACHE_TAG_LENGTH; // TLB line tag
8899
};
89100
} address_t;
90101

0 commit comments

Comments
 (0)