OpenCores
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();

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.