URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1730 to Rev 1731
- ↔ Reverse comparison
Rev 1730 → Rev 1731
/trunk/or1ksim/cpu/common/stats.c
37,6 → 37,7
#include "sprs.h" |
#include "debug.h" |
#include "stats.h" |
#include "icache_model.h" |
|
struct branchstat { |
int taken; |
175,7 → 176,7
} else |
PRINTF("BTIC simulation disabled. Enabled it to see BTIC analysis\n"); |
|
if (config.ic.enabled) { |
if(ic_state->enabled) { |
PRINTF("IC read: hit %d(%d%%), miss %d\n", ic_stats.readhit, (ic_stats.readhit * 100) / SD(ic_stats.readhit + ic_stats.readmiss), ic_stats.readmiss); |
} else |
PRINTF("No ICache. Enable it to see IC results.\n"); |
/trunk/or1ksim/cpu/common/abstract.c
494,7 → 494,7
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); |
|
if (config.ic.enabled) |
if(ic_state->enabled) |
temp = ic_simulate_fetch(phys_memaddr, memaddr); |
else |
temp = evalsim_mem32(phys_memaddr, memaddr); |
/trunk/or1ksim/cache/icache_model.h
20,7 → 20,29
#define MAX_IC_SETS 1024 |
#define MAX_IC_WAYS 32 |
#define MAX_IC_BLOCK_SIZE 4 /* In words */ |
|
|
struct ic { |
uint8_t *mem; |
unsigned int *lrus; |
oraddr_t *tags; |
|
int enabled; /* Whether instruction cache is enabled */ |
unsigned int nways; /* Number of IC ways */ |
unsigned int nsets; /* Number of IC sets */ |
unsigned int blocksize; /* IC entry size */ |
unsigned int ustates; /* number of IC usage states */ |
int missdelay; /* How much cycles does the miss cost */ |
int hitdelay; /* How much cycles does the hit cost */ |
unsigned int blocksize_log2; /* log2(blocksize) */ |
oraddr_t set_mask; /* Mask to get set number */ |
oraddr_t tagaddr_mask; /* Mask to get tag address */ |
oraddr_t last_way; /* nways * nsets */ |
oraddr_t block_offset_mask; /* mask to get offset into block */ |
oraddr_t block_mask; /* mask to get block number */ |
unsigned int ustates_reload; /* ustates - 1 */ |
}; |
|
extern struct ic *ic_state; |
|
uint32_t ic_simulate_fetch(oraddr_t fetchaddr, oraddr_t virt_addr); |
void ic_inv(oraddr_t dataaddr); |
void ic_info(); |
/trunk/or1ksim/cache/icache_model.c
50,30 → 50,30
|
extern struct dev_memarea *cur_area; |
|
uint8_t ic_mem[MAX_IC_BLOCK_SIZE * MAX_IC_WAYS * MAX_IC_SETS * 4]; |
oraddr_t ic_tags[MAX_IC_WAYS * MAX_IC_SETS]; |
int ic_lrus[MAX_IC_WAYS * MAX_IC_SETS]; |
struct ic *ic_state; |
|
void ic_info() |
static void ic_info(void *dat) |
{ |
struct ic *ic = dat; |
if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)) { |
PRINTF("ICache not implemented. Set UPR[ICP].\n"); |
return; |
} |
|
PRINTF("Instruction cache %dKB: ", config.ic.nsets * config.ic.blocksize * config.ic.nways / 1024); |
PRINTF("%d ways, %d sets, block size %d bytes\n", config.ic.nways, config.ic.nsets, config.ic.blocksize); |
PRINTF("Instruction cache %dKB: ", ic->nsets * ic->blocksize * ic->nways / 1024); |
PRINTF("%d ways, %d sets, block size %d bytes\n", ic->nways, ic->nsets, |
ic->blocksize); |
} |
|
/* First check if instruction is already in the cache and if it is: |
- increment IC read hit stats, |
- set 'lru' at this way to config.ic.ustates - 1 and |
- set 'lru' at this way to ic->ustates - 1 and |
decrement 'lru' of other ways unless they have reached 0, |
- read insn from the cache line |
and if not: |
- increment IC read miss stats |
- find lru way and entry and replace old tag with tag of the 'fetchaddr' |
- set 'lru' with config.ic.ustates - 1 and decrement 'lru' of other |
- set 'lru' with ic->ustates - 1 and decrement 'lru' of other |
ways unless they have reached 0 |
- refill cache line |
*/ |
88,6 → 88,7
oraddr_t reload_addr; |
oraddr_t reload_end; |
unsigned int minlru; |
struct ic *ic = ic_state; |
|
/* ICache simulation enabled/disabled. */ |
if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP) || |
100,57 → 101,57
} |
|
/* Which set to check out? */ |
set = (fetchaddr & config.ic.set_mask) >> config.ic.blocksize_log2; |
tagaddr = fetchaddr & config.ic.tagaddr_mask; |
set = (fetchaddr & ic->set_mask) >> ic->blocksize_log2; |
tagaddr = fetchaddr & ic->tagaddr_mask; |
|
/* Scan all ways and try to find a matching way. */ |
for(way = set; way < config.ic.last_way; way += config.ic.nsets) { |
if(ic_tags[way] == tagaddr) { |
for(way = set; way < ic->last_way; way += ic->nsets) { |
if(ic->tags[way] == tagaddr) { |
ic_stats.readhit++; |
|
for(lru_way = set; lru_way < config.ic.last_way; |
lru_way += config.ic.nsets) |
if(ic_lrus[lru_way] > ic_lrus[way]) |
ic_lrus[lru_way]--; |
ic_lrus[way] = config.ic.ustates_reload; |
runtime.sim.mem_cycles += config.ic.hitdelay; |
way <<= config.ic.blocksize_log2; |
return *(uint32_t *)&ic_mem[way | (fetchaddr & config.ic.block_offset_mask)]; |
for(lru_way = set; lru_way < ic->last_way; |
lru_way += ic->nsets) |
if(ic->lrus[lru_way] > ic->lrus[way]) |
ic->lrus[lru_way]--; |
ic->lrus[way] = ic->ustates_reload; |
runtime.sim.mem_cycles += ic->hitdelay; |
way <<= ic->blocksize_log2; |
return *(uint32_t *)&ic->mem[way | (fetchaddr & ic->block_offset_mask)]; |
} |
} |
|
minlru = config.ic.ustates_reload; |
minlru = ic->ustates_reload; |
way = set; |
|
ic_stats.readmiss++; |
|
for(lru_way = set; lru_way < config.ic.last_way; lru_way += config.ic.nsets) { |
if(ic_lrus[lru_way] < minlru) { |
for(lru_way = set; lru_way < ic->last_way; lru_way += ic->nsets) { |
if(ic->lrus[lru_way] < minlru) { |
way = lru_way; |
minlru = ic_lrus[lru_way]; |
minlru = ic->lrus[lru_way]; |
} |
} |
|
ic_tags[way] = tagaddr; |
for(lru_way = set; lru_way < config.ic.last_way; lru_way += config.ic.nsets) |
if(ic_lrus[lru_way]) |
ic_lrus[lru_way]--; |
ic_lrus[way] = config.ic.ustates_reload; |
ic->tags[way] = tagaddr; |
for(lru_way = set; lru_way < ic->last_way; lru_way += ic->nsets) |
if(ic->lrus[lru_way]) |
ic->lrus[lru_way]--; |
ic->lrus[way] = ic->ustates_reload; |
|
reload_addr = fetchaddr & config.ic.block_offset_mask; |
reload_end = reload_addr + config.ic.blocksize; |
reload_addr = fetchaddr & ic->block_offset_mask; |
reload_end = reload_addr + ic->blocksize; |
|
fetchaddr &= config.ic.block_mask; |
fetchaddr &= ic->block_mask; |
|
way <<= config.ic.blocksize_log2; |
way <<= ic->blocksize_log2; |
for(; reload_addr < reload_end; reload_addr += 4) { |
tmp = *(uint32_t *)&ic_mem[way | (reload_addr & config.ic.block_offset_mask)] = |
tmp = *(uint32_t *)&ic->mem[way | (reload_addr & ic->block_offset_mask)] = |
/* FIXME: What is the virtual address meant to be? (ie. What happens if |
* we read out of memory while refilling a cache line?) */ |
evalsim_mem32(fetchaddr | (reload_addr & config.ic.block_offset_mask), 0); |
evalsim_mem32(fetchaddr | (reload_addr & ic->block_offset_mask), 0); |
if(!cur_area) { |
ic_tags[way >> config.ic.blocksize_log2] = -1; |
ic_lrus[way >> config.ic.blocksize_log2] = 0; |
ic->tags[way >> ic->blocksize_log2] = -1; |
ic->lrus[way >> ic->blocksize_log2] = 0; |
return 0; |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", |
157,8 → 158,8
fetchaddr, tmp); |
} |
|
runtime.sim.mem_cycles += config.ic.missdelay; |
return *(uint32_t *)&ic_mem[way | (reload_addr & config.ic.block_offset_mask)]; |
runtime.sim.mem_cycles += ic->missdelay; |
return *(uint32_t *)&ic->mem[way | (reload_addr & ic->block_offset_mask)]; |
} |
|
/* First check if data is already in the cache and if it is: |
171,28 → 172,29
oraddr_t set; |
oraddr_t way; |
oraddr_t tagaddr; |
struct ic *ic = ic_state; |
|
if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)) |
return; |
|
/* Which set to check out? */ |
set = (dataaddr & config.ic.set_mask) >> config.ic.blocksize_log2; |
set = (dataaddr & ic->set_mask) >> ic->blocksize_log2; |
|
if (!(cpu_state.sprs[SPR_SR] & SPR_SR_ICE)) { |
for(way = set; way < config.ic.last_way; way += config.ic.nsets) { |
ic_tags[way] = -1; |
ic_lrus[way] = 0; |
for(way = set; way < ic->last_way; way += ic->nsets) { |
ic->tags[way] = -1; |
ic->lrus[way] = 0; |
} |
return; |
} |
|
tagaddr = dataaddr & config.ic.tagaddr_mask; |
tagaddr = dataaddr & ic->tagaddr_mask; |
|
/* Scan all ways and try to find a matching way. */ |
for(way = set; way < config.ic.last_way; way += config.ic.nsets) { |
if(ic_tags[way] == tagaddr) { |
ic_tags[way] = -1; |
ic_lrus[way] = 0; |
for(way = set; way < ic->last_way; way += ic->nsets) { |
if(ic->tags[way] == tagaddr) { |
ic->tags[way] = -1; |
ic->lrus[way] = 0; |
} |
} |
} |
200,7 → 202,8
/*-----------------------------------------------------[ IC configuration ]---*/ |
static void ic_enabled(union param_val val, void *dat) |
{ |
config.ic.enabled = val.int_val; |
struct ic *ic = dat; |
ic->enabled = val.int_val; |
if(val.int_val) |
cpu_state.sprs[SPR_UPR] |= SPR_UPR_ICP; |
else |
209,8 → 212,9
|
static void ic_nsets(union param_val val, void *dat) |
{ |
struct ic *ic = dat; |
if (is_power2(val.int_val) && val.int_val <= MAX_IC_SETS){ |
config.ic.nsets = val.int_val; |
ic->nsets = val.int_val; |
cpu_state.sprs[SPR_ICCFGR] &= ~SPR_ICCFGR_NCS; |
cpu_state.sprs[SPR_ICCFGR] |= log2_int(val.int_val) << 3; |
} |
223,8 → 227,9
|
static void ic_nways(union param_val val, void *dat) |
{ |
struct ic *ic = dat; |
if (is_power2(val.int_val) && val.int_val <= MAX_IC_WAYS) { |
config.ic.nways = val.int_val; |
ic->nways = val.int_val; |
cpu_state.sprs[SPR_ICCFGR] &= ~SPR_ICCFGR_NCW; |
cpu_state.sprs[SPR_ICCFGR] |= log2_int(val.int_val); |
} |
238,8 → 243,9
|
static void ic_blocksize(union param_val val, void *dat) |
{ |
struct ic *ic = dat; |
if (is_power2(val.int_val)){ |
config.ic.blocksize = val.int_val; |
ic->blocksize = val.int_val; |
cpu_state.sprs[SPR_ICCFGR] &= ~SPR_ICCFGR_CBS; |
cpu_state.sprs[SPR_ICCFGR] |= log2_int(val.int_val) << 7; |
} else |
248,8 → 254,9
|
static void ic_ustates(union param_val val, void *dat) |
{ |
struct ic *ic = dat; |
if (val.int_val >= 2 && val.int_val <= 4) |
config.ic.ustates = val.int_val; |
ic->ustates = val.int_val; |
else |
CONFIG_ERROR("invalid USTATE."); |
} |
256,28 → 263,77
|
static void ic_missdelay(union param_val val, void *dat) |
{ |
config.ic.missdelay = val.int_val; |
struct ic *ic = dat; |
ic->missdelay = val.int_val; |
} |
|
static void ic_hitdelay(union param_val val, void *dat) |
{ |
config.ic.hitdelay = val.int_val; |
struct ic *ic = dat; |
ic->hitdelay = val.int_val; |
} |
|
static void *ic_start_sec(void) |
{ |
struct ic *ic; |
|
if(!(ic = malloc(sizeof(struct ic)))) { |
fprintf(stderr, "OOM\n"); |
exit(1); |
} |
|
ic->enabled = 0; |
ic->hitdelay = 1; |
ic->missdelay = 1; |
ic->nways = 0; |
ic->nsets = 0; |
ic->blocksize = 0; |
ic->ustates = 0; |
ic->mem = NULL; |
ic->lrus = NULL; |
ic->tags = NULL; |
|
ic_state = ic; |
|
return ic; |
} |
|
static void ic_end_sec(void *dat) |
{ |
config.ic.blocksize_log2 = log2_int(config.ic.blocksize); |
config.ic.set_mask = (config.ic.nsets - 1) << config.ic.blocksize_log2; |
config.ic.tagaddr_mask = ~((config.ic.nsets * config.ic.blocksize) - 1); |
config.ic.block_offset_mask = config.ic.blocksize - 1; |
config.ic.block_mask = ~config.ic.block_offset_mask; |
config.ic.last_way = config.ic.nsets * config.ic.nways; |
config.ic.ustates_reload = config.ic.ustates - 1; |
struct ic *ic = dat; |
unsigned int size = ic->nways * ic->nsets * ic->blocksize; |
|
if(size) { |
if(!(ic->mem = malloc(size))) { |
fprintf(stderr, "OOM\n"); |
exit(1); |
} |
if(!(ic->lrus = malloc(ic->nsets * ic->nways * sizeof(unsigned int)))) { |
fprintf(stderr, "OOM\n"); |
exit(1); |
} |
if(!(ic->tags = malloc(ic->nsets * ic->nways * sizeof(oraddr_t)))) { |
fprintf(stderr, "OOM\n"); |
exit(1); |
} |
} else |
ic->enabled = 0; |
|
ic->blocksize_log2 = log2_int(ic->blocksize); |
ic->set_mask = (ic->nsets - 1) << ic->blocksize_log2; |
ic->tagaddr_mask = ~((ic->nsets * ic->blocksize) - 1); |
ic->block_offset_mask = ic->blocksize - 1; |
ic->block_mask = ~ic->block_offset_mask; |
ic->last_way = ic->nsets * ic->nways; |
ic->ustates_reload = ic->ustates - 1; |
|
if(ic->enabled) |
reg_sim_stat(ic_info, dat); |
} |
|
void reg_ic_sec(void) |
{ |
struct config_section *sec = reg_config_sec("ic", NULL, ic_end_sec); |
struct config_section *sec = reg_config_sec("ic", ic_start_sec, ic_end_sec); |
|
reg_config_param(sec, "enabled", paramt_int, ic_enabled); |
reg_config_param(sec, "nsets", paramt_int, ic_nsets); |
/trunk/or1ksim/sim-cmd.c
479,7 → 479,6
sprs_status(); |
PRINTF ("\n"); |
memory_table_status (); |
if (config.ic.enabled) ic_info(); |
if (config.dc.enabled) dc_info(); |
|
if (config.bpb.enabled) bpb_info(); |