Skip to content

Commit

Permalink
sram cache
Browse files Browse the repository at this point in the history
  • Loading branch information
yangminz committed May 15, 2021
1 parent 615fc1b commit 17d4782
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 45 deletions.
18 changes: 9 additions & 9 deletions src/hardware/cpu/isa.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ static void mov_handler(od_t *src_od, od_t *dst_od)
{
// src: register
// dst: virtual address
write64bits_dram(
cpu_write64bits_dram(
va2pa(dst),
*(uint64_t *)src);
increase_pc();
Expand All @@ -532,7 +532,7 @@ static void mov_handler(od_t *src_od, od_t *dst_od)
{
// src: virtual address
// dst: register
*(uint64_t *)dst = read64bits_dram(va2pa(src));
*(uint64_t *)dst = cpu_read64bits_dram(va2pa(src));
increase_pc();
cpu_flags.__flags_value = 0;
return;
Expand All @@ -558,7 +558,7 @@ static void push_handler(od_t *src_od, od_t *dst_od)
// src: register
// dst: empty
cpu_reg.rsp = cpu_reg.rsp - 8;
write64bits_dram(
cpu_write64bits_dram(
va2pa(cpu_reg.rsp),
*(uint64_t *)src);
increase_pc();
Expand All @@ -576,7 +576,7 @@ static void pop_handler(od_t *src_od, od_t *dst_od)
{
// src: register
// dst: empty
uint64_t old_val = read64bits_dram(
uint64_t old_val = cpu_read64bits_dram(
va2pa(cpu_reg.rsp));
cpu_reg.rsp = cpu_reg.rsp + 8;
*(uint64_t *)src = old_val;
Expand All @@ -592,7 +592,7 @@ static void leave_handler(od_t *src_od, od_t *dst_od)
cpu_reg.rsp = cpu_reg.rbp;

// popq %rbp
uint64_t old_val = read64bits_dram(
uint64_t old_val = cpu_read64bits_dram(
va2pa(cpu_reg.rsp));
cpu_reg.rsp = cpu_reg.rsp + 8;
cpu_reg.rbp = old_val;
Expand All @@ -609,7 +609,7 @@ static void call_handler(od_t *src_od, od_t *dst_od)
// dst: empty
// push the return value
cpu_reg.rsp = cpu_reg.rsp - 8;
write64bits_dram(
cpu_write64bits_dram(
va2pa(cpu_reg.rsp),
cpu_pc.rip + sizeof(char) * MAX_INSTRUCTION_CHAR);
// jump to target function address
Expand All @@ -626,7 +626,7 @@ static void ret_handler(od_t *src_od, od_t *dst_od)
// src: empty
// dst: empty
// pop rsp
uint64_t ret_addr = read64bits_dram(
uint64_t ret_addr = cpu_read64bits_dram(
va2pa(cpu_reg.rsp));
cpu_reg.rsp = cpu_reg.rsp + 8;
// jump to return address
Expand Down Expand Up @@ -707,7 +707,7 @@ static void cmp_handler(od_t *src_od, od_t *dst_od)
// src: register (value: int64_t bit map)
// dst: register (value: int64_t bit map)
// dst = dst - src = dst + (-src)
uint64_t dval = read64bits_dram(va2pa(dst));
uint64_t dval = cpu_read64bits_dram(va2pa(dst));
uint64_t val = dval + (~src + 1);

int val_sign = ((val >> 63) & 0x1);
Expand Down Expand Up @@ -761,7 +761,7 @@ void instruction_cycle()
{
// FETCH: get the instruction string by program counter
char inst_str[MAX_INSTRUCTION_CHAR + 10];
readinst_dram(va2pa(cpu_pc.rip), inst_str);
cpu_readinst_dram(va2pa(cpu_pc.rip), inst_str);

debug_printf(DEBUG_INSTRUCTIONCYCLE, "%8lx %s\n", cpu_pc.rip, inst_str);

Expand Down
202 changes: 192 additions & 10 deletions src/hardware/cpu/sram.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
*/

#include "headers/address.h"
#include "headers/memory.h"
#include <stdint.h>
#include <assert.h>

#define NUM_CACHE_LINE_PER_SET (8)

// write-back and write-allocate
typedef enum
{
CACHE_LINE_INVALID,
Expand All @@ -23,8 +26,9 @@ typedef enum
typedef struct
{
sram_cacheline_state_t state;
int time; // timer to find LRU line inside one set
uint64_t tag;
uint8_t block[(1 >> SRAM_CACHE_OFFSET_LENGTH)];
uint8_t block[(1 << SRAM_CACHE_OFFSET_LENGTH)];
} sram_cacheline_t;

typedef struct
Expand All @@ -34,34 +38,212 @@ typedef struct

typedef struct
{
sram_cacheset_t sets[(1 >> SRAM_CACHE_INDEX_LENGTH)];
sram_cacheset_t sets[(1 << SRAM_CACHE_INDEX_LENGTH)];
} sram_cache_t;

static sram_cache_t cache;

uint8_t sram_cache_read(address_t paddr)
uint8_t sram_cache_read(uint64_t paddr_value)
{
address_t paddr = {
.paddr_value = paddr_value,
};

sram_cacheset_t set = cache.sets[paddr.CI];

// update LRU time
sram_cacheline_t *victim = NULL;
sram_cacheline_t *invalid = NULL;
int max_time = -1;

for (int i = 0; i < NUM_CACHE_LINE_PER_SET; ++ i)
{
set.lines[i].time ++;

if (max_time < set.lines[i].time)
{
// select this line as victim by LRU policy
// replace it when all lines are valid
victim = &(set.lines[i]);
max_time = set.lines[i].time;
}

if (set.lines[i].state == CACHE_LINE_INVALID)
{
// exist one invalid line as candidate for cache miss
invalid = &(set.lines[i]);
}
}

// try cache hit
for (int i = 0; i < NUM_CACHE_LINE_PER_SET; ++ i)
{
sram_cacheline_t line = set.lines[i];

if (line.state != CACHE_LINE_INVALID && line.tag == paddr.CT)
{
// cache hit
// TODO: update LRU
// update LRU time
line.time = 0;

// find the byte
return line.block[paddr.CO];
}
}

// cache miss: load from memory
// TODO: update LRU
// TODO: select one victim by replacement policy if set is full

return 0;
// try to find one free cache line
if (invalid != NULL)
{
// load data from DRAM to this invalid cache line
bus_read_cacheline(paddr.paddr_value, &(invalid->block));

// update cache line state
invalid->state = CACHE_LINE_CLEAN;

// update LRU
invalid->time = 0;

// update tag
invalid->tag = paddr.CT;

return invalid->block[paddr.CO];
}

// no free cache line, use LRU policy
assert(victim != NULL);

if (victim->state == CACHE_LINE_DIRTY)
{
// write back the dirty line to dram
bus_write_cacheline(paddr.paddr_value, victim);
}
// if CACHE_LINE_CLEAN discard this victim directly
// update state
victim->state = CACHE_LINE_INVALID;

// read from dram
// load data from DRAM to this invalid cache line
bus_read_cacheline(paddr.paddr_value, &(victim->block));

// update cache line state
victim->state = CACHE_LINE_CLEAN;

// update LRU
victim->time = 0;

// update tag
victim->tag = paddr.CT;

return victim->block[paddr.CO];
}

void sram_cache_write(address_t paddr, uint8_t data)
void sram_cache_write(uint64_t paddr_value, uint8_t data)
{
return;
}
address_t paddr = {
.paddr_value = paddr_value,
};

sram_cacheset_t set = cache.sets[paddr.CI];

// update LRU time
sram_cacheline_t *victim = NULL;
sram_cacheline_t *invalid = NULL; // for write-allocate
int max_time = -1;

for (int i = 0; i < NUM_CACHE_LINE_PER_SET; ++ i)
{
set.lines[i].time ++;

if (max_time < set.lines[i].time)
{
// select this line as victim by LRU policy
// replace it when all lines are valid
victim = &(set.lines[i]);
max_time = set.lines[i].time;
}

if (set.lines[i].state == CACHE_LINE_INVALID)
{
// exist one invalid line as candidate for cache miss
invalid = &(set.lines[i]);
}
}

// try cache hit
for (int i = 0; i < NUM_CACHE_LINE_PER_SET; ++ i)
{
sram_cacheline_t line = set.lines[i];

if (line.state != CACHE_LINE_INVALID && line.tag == paddr.CT)
{
// cache hit

// update LRU time
line.time = 0;

// find the byte
line.block[paddr.CO] = data;

// update state
line.state = CACHE_LINE_DIRTY;

return;
}
}

// cache miss: load from memory

// write-allocate

// try to find one free cache line
if (invalid != NULL)
{
// load data from DRAM to this invalid cache line
bus_read_cacheline(paddr.paddr_value, &(invalid->block));

// update cache line state
invalid->state = CACHE_LINE_DIRTY;

// update LRU
invalid->time = 0;

// update tag
invalid->tag = paddr.CT;

// write data
invalid->block[paddr.CO] = data;

return;
}

// no free cache line, use LRU policy
assert(victim != NULL);

if (victim->state == CACHE_LINE_DIRTY)
{
// write back the dirty line to dram
bus_write_cacheline(paddr.paddr_value, victim);
}
// if CACHE_LINE_CLEAN discard this victim directly
// update state
victim->state = CACHE_LINE_INVALID;

// read from dram
// write-allocate
// load data from DRAM to this invalid cache line
bus_read_cacheline(paddr.paddr_value, &(victim->block));

// update cache line state
victim->state = CACHE_LINE_DIRTY;

// update LRU
victim->time = 0;

// update tag
victim->tag = paddr.CT;

victim->block[paddr.CO] = data;
}

Loading

0 comments on commit 17d4782

Please sign in to comment.