Skip to content

Commit

Permalink
add TLB cache
Browse files Browse the repository at this point in the history
  • Loading branch information
yangminz committed Aug 8, 2021
1 parent fe11344 commit dedc042
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 53 deletions.
134 changes: 133 additions & 1 deletion src/hardware/cpu/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,151 @@
#include "headers/common.h"
#include "headers/address.h"

// -------------------------------------------- //
// TLB cache struct
// -------------------------------------------- //

#define NUM_TLB_CACHE_LINE_PER_SET (8)

typedef struct
{
int valid;
uint64_t tag;
uint64_t ppn;
} tlb_cacheline_t;

typedef struct
{
tlb_cacheline_t lines[NUM_TLB_CACHE_LINE_PER_SET];
} tlb_cacheset_t;

typedef struct
{
tlb_cacheset_t sets[(1 << TLB_CACHE_INDEX_LENGTH)];
} tlb_cache_t;

static tlb_cache_t mmu_tlb;

static uint64_t page_walk(uint64_t vaddr_value);
static void page_fault_handler(pte4_t *pte, address_t vaddr);

static int read_tlb(uint64_t vaddr_value, uint64_t *paddr_value_ptr,
int *free_tlb_line_index);
static int write_tlb(uint64_t vaddr_value, uint64_t paddr_value,
int free_tlb_line_index);

int swap_in(uint64_t daddr, uint64_t ppn);
int swap_out(uint64_t daddr, uint64_t ppn);

// consider this function va2pa as functional
uint64_t va2pa(uint64_t vaddr)
{
uint64_t paddr = 0;

#ifdef USE_TLB_HARDWARE
int free_tlb_line_index = -1;
int tlb_hit = read_tlb(vaddr, &paddr, &free_tlb_line_index);

// TODO: add flag to read tlb failed
if (tlb_hit)
{
// TLB read hit
return paddr;
}

// TLB read miss
#endif

// assume that page_walk is consuming much time
paddr = page_walk(vaddr);

#ifdef USE_TLB_HARDWARE
// refresh TLB
// TODO: check if this paddr from page table is a legal address
if (paddr != 0)
{
// TLB write
if (write_tlb(vaddr, paddr, free_tlb_line_index) == 1)
{
return paddr;
}
}
#endif

// use page table as va2pa
return page_walk(vaddr);
return paddr;
}

static int read_tlb(uint64_t vaddr_value, uint64_t *paddr_value_ptr,
int *free_tlb_line_index)
{
address_t vaddr = {
.address_value = vaddr_value
};

tlb_cacheset_t *set = &mmu_tlb.sets[vaddr.tlbi];
*free_tlb_line_index = -1;

for (int i = 0; i < NUM_TLB_CACHE_LINE_PER_SET; ++ i)
{
tlb_cacheline_t *line = &set->lines[i];

if (line->valid == 0)
{
*free_tlb_line_index = i;
}

if (line->tag == vaddr.tlbt &&
line->valid == 1)
{
// TLB read hit
*paddr_value_ptr = line->ppn;
return 1;
}
}

// TLB read miss
*paddr_value_ptr = NULL;
return 0;
}

static int write_tlb(uint64_t vaddr_value, uint64_t paddr_value,
int free_tlb_line_index)
{
address_t vaddr = {
.address_value = vaddr_value
};

address_t paddr = {
.address_value = paddr_value
};

tlb_cacheset_t *set = &mmu_tlb.sets[vaddr.tlbi];

if (0 <= free_tlb_line_index && free_tlb_line_index < NUM_TLB_CACHE_LINE_PER_SET)
{
tlb_cacheline_t *line = &set->lines[free_tlb_line_index];

line->valid = 1;
line->ppn = paddr.ppn;
line->tag = vaddr.tlbt;

return 1;
}

// no free TLB cache line, select one RANDOM victim
int random_victim_index = random() % NUM_TLB_CACHE_LINE_PER_SET;

tlb_cacheline_t *line = &set->lines[random_victim_index];

line->valid = 1;
line->ppn = paddr.ppn;
line->tag = vaddr.tlbt;

return 1;
}


// input - virtual address
// output - physical address
static uint64_t page_walk(uint64_t vaddr_value)
Expand Down
88 changes: 41 additions & 47 deletions src/hardware/memory/dram.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,55 @@ e.g. write 0x00007fd357a02ae0 to cache, the memory lapping should be:
// memory accessing used in instructions
uint64_t cpu_read64bits_dram(uint64_t paddr)
{
if (DEBUG_ENABLE_SRAM_CACHE == 1)
#ifdef DEBUG_ENABLE_SRAM_CACHE
// try to load uint64_t from SRAM cache
// little-endian
uint64_t val = 0x0;
for (int i = 0; i < 8; ++ i)
{
// try to load uint64_t from SRAM cache
// little-endian
uint64_t val = 0x0;
for (int i = 0; i < 8; ++ i)
{
val += (sram_cache_read(paddr + i) << (i * 8));
}
return val;
}
else
{
// read from DRAM directly
// little-endian
uint64_t val = 0x0;

val += (((uint64_t)pm[paddr + 0 ]) << 0);
val += (((uint64_t)pm[paddr + 1 ]) << 8);
val += (((uint64_t)pm[paddr + 2 ]) << 16);
val += (((uint64_t)pm[paddr + 3 ]) << 24);
val += (((uint64_t)pm[paddr + 4 ]) << 32);
val += (((uint64_t)pm[paddr + 5 ]) << 40);
val += (((uint64_t)pm[paddr + 6 ]) << 48);
val += (((uint64_t)pm[paddr + 7 ]) << 56);

return val;
val += (sram_cache_read(paddr + i) << (i * 8));
}
return val;
#elif
// read from DRAM directly
// little-endian
uint64_t val = 0x0;

val += (((uint64_t)pm[paddr + 0 ]) << 0);
val += (((uint64_t)pm[paddr + 1 ]) << 8);
val += (((uint64_t)pm[paddr + 2 ]) << 16);
val += (((uint64_t)pm[paddr + 3 ]) << 24);
val += (((uint64_t)pm[paddr + 4 ]) << 32);
val += (((uint64_t)pm[paddr + 5 ]) << 40);
val += (((uint64_t)pm[paddr + 6 ]) << 48);
val += (((uint64_t)pm[paddr + 7 ]) << 56);

return val;
#endif
}

void cpu_write64bits_dram(uint64_t paddr, uint64_t data)
{
if (DEBUG_ENABLE_SRAM_CACHE == 1)
{
// try to write uint64_t to SRAM cache
// little-endian
for (int i = 0; i < 8; ++ i)
{
sram_cache_write(paddr + i, (data >> (i * 8)) & 0xff);
}
return;
}
else
#ifdef DEBUG_ENABLE_SRAM_CACHE
// try to write uint64_t to SRAM cache
// little-endian
for (int i = 0; i < 8; ++ i)
{
// write to DRAM directly
// little-endian
pm[paddr + 0] = (data >> 0 ) & 0xff;
pm[paddr + 1] = (data >> 8 ) & 0xff;
pm[paddr + 2] = (data >> 16) & 0xff;
pm[paddr + 3] = (data >> 24) & 0xff;
pm[paddr + 4] = (data >> 32) & 0xff;
pm[paddr + 5] = (data >> 40) & 0xff;
pm[paddr + 6] = (data >> 48) & 0xff;
pm[paddr + 7] = (data >> 56) & 0xff;
sram_cache_write(paddr + i, (data >> (i * 8)) & 0xff);
}
return;
#elif
// write to DRAM directly
// little-endian
pm[paddr + 0] = (data >> 0 ) & 0xff;
pm[paddr + 1] = (data >> 8 ) & 0xff;
pm[paddr + 2] = (data >> 16) & 0xff;
pm[paddr + 3] = (data >> 24) & 0xff;
pm[paddr + 4] = (data >> 32) & 0xff;
pm[paddr + 5] = (data >> 40) & 0xff;
pm[paddr + 6] = (data >> 48) & 0xff;
pm[paddr + 7] = (data >> 56) & 0xff;
#endif
}

void cpu_readinst_dram(uint64_t paddr, char *buf)
Expand Down
21 changes: 16 additions & 5 deletions src/headers/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@
#define VIRTUAL_PAGE_NUMBER_LENGTH (9) // 9 + 9 + 9 + 9 = 36
#define VIRTUAL_ADDRESS_LENGTH (48)

#define TLB_CACHE_OFFSET_LENGTH (12)
#define TLB_CACHE_INDEX_LENGTH (4)
#define TLB_CACHE_TAG_LENGTH (32)

/*
+--------+--------+--------+--------+---------------+
| VPN3 | VPN2 | VPN1 | VPN0 | |
| VPN1 | VPN2 | VPN3 | VPN4 | |
+--------+--------+--------+-+------+ VPO |
| TLBT | TLBI | |
+---------------+------------+------+---------------+
Expand All @@ -62,6 +65,14 @@ typedef union
};
};

// sram cache: 52
struct
{
uint64_t co : SRAM_CACHE_OFFSET_LENGTH;
uint64_t ci : SRAM_CACHE_INDEX_LENGTH;
uint64_t ct : SRAM_CACHE_TAG_LENGTH;
};

// virtual address: 48
struct
{
Expand All @@ -79,12 +90,12 @@ typedef union
};
};

// sram cache: 52
// TLB cache: 48
struct
{
uint64_t co : SRAM_CACHE_OFFSET_LENGTH;
uint64_t ci : SRAM_CACHE_INDEX_LENGTH;
uint64_t ct : SRAM_CACHE_TAG_LENGTH;
uint64_t tlbo : TLB_CACHE_OFFSET_LENGTH; // virtual page offset
uint64_t tlbi : TLB_CACHE_INDEX_LENGTH; // TLB set index
uint64_t tlbt : TLB_CACHE_TAG_LENGTH; // TLB line tag
};
} address_t;

Expand Down

0 comments on commit dedc042

Please sign in to comment.