URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1537 to Rev 1538
- ↔ Reverse comparison
Rev 1537 → Rev 1538
/trunk/or1ksim/sim-config.h
42,6 → 42,12
int nways; /* Number of ITLB ways */ |
int nsets; /* Number of ITLB sets */ |
int pagesize; /* ITLB page size */ |
int pagesize_log2; /* ITLB page size (log2(pagesize)) */ |
oraddr_t page_offset_mask; /* Address mask to get page offset */ |
oraddr_t page_mask; /* Page number mask (diff. from vpn) */ |
oraddr_t vpn_mask; /* Address mask to get vpn */ |
int lru_reload; /* What to reload the lru value to */ |
oraddr_t set_mask; /* Mask to get set of an address */ |
int entrysize; /* ITLB entry size */ |
int ustates; /* number of ITLB usage states */ |
int missdelay; /* How much cycles does the miss cost */ |
/trunk/or1ksim/cpu/common/abstract.h
160,7 → 160,7
#endif /* ! LONGEST */ |
|
/* Returns the page that addr belongs to */ |
#define IADDR_PAGE(addr) ((addr) & ~(config.immu.pagesize - 1)) |
#define IADDR_PAGE(addr) ((addr) & config.immu.page_mask) |
|
/* History of execution */ |
#define HISTEXEC_LEN 200 |
/trunk/or1ksim/mmu/immu.c
17,7 → 17,7
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* IMMU model (not functional yet, currently just copy of data cache). */ |
/* IMMU model, perfectly functional. */ |
|
#include "config.h" |
|
42,13 → 42,49
|
/* Insn MMU */ |
|
static inline oraddr_t immu_simulate_tlb(oraddr_t virtaddr) |
/* Precalculates some values for use during address translation */ |
void init_immu(void) |
{ |
int set, way = -1; |
config.immu.pagesize_log2 = log2(config.immu.pagesize); |
config.immu.page_offset_mask = config.immu.pagesize - 1; |
config.immu.page_mask = ~config.immu.page_offset_mask; |
config.immu.vpn_mask = ~((config.immu.pagesize * config.immu.nsets) - 1); |
config.immu.set_mask = config.immu.nsets - 1; |
config.immu.lru_reload = (config.immu.set_mask << 6) & SPR_ITLBMR_LRU; |
} |
|
inline uorreg_t *immu_find_tlbmr(oraddr_t virtaddr, uorreg_t **itlbmr_lru) |
{ |
int set; |
int i; |
oraddr_t tagaddr; |
oraddr_t vpn, ppn; |
oraddr_t vpn; |
uorreg_t *itlbmr; |
|
/* Which set to check out? */ |
set = IADDR_PAGE(virtaddr) >> config.immu.pagesize_log2; |
set &= config.immu.set_mask; |
vpn = virtaddr & config.immu.vpn_mask; |
|
itlbmr = &cpu_state.sprs[SPR_ITLBMR_BASE(0) + set]; |
*itlbmr_lru = itlbmr; |
|
/* Scan all ways and try to find a matching way. */ |
/* FIXME: Should this be reversed? */ |
for(i = config.immu.nways; i; i--, itlbmr += (128 * 2)) { |
if(((*itlbmr & config.immu.vpn_mask) == vpn) && (*itlbmr & SPR_ITLBMR_V)) |
return itlbmr; |
} |
|
return NULL; |
} |
|
oraddr_t immu_translate(oraddr_t virtaddr) |
{ |
int i; |
uorreg_t *itlbmr; |
uorreg_t *itlbtr; |
uorreg_t *itlbmr_lru; |
|
if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) || |
!(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) { |
insn_ci = (virtaddr >= 0x80000000); |
55,85 → 91,81
return virtaddr; |
} |
|
TRACE("IMMU enabled, checking mmu ways\n"); |
itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru); |
|
/* Which set to check out? */ |
set = (virtaddr / config.immu.pagesize) % config.immu.nsets; |
tagaddr = (virtaddr / config.immu.pagesize) / config.immu.nsets; |
vpn = virtaddr / (config.immu.pagesize * config.immu.nsets); |
|
/* Scan all ways and try to find a matching way. */ |
for (i = 0; i < config.immu.nways; i++) |
if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] / (config.immu.pagesize * config.immu.nsets)) == vpn) && |
(cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_V)) |
way = i; |
|
/* Did we find our tlb entry? */ |
if (way >= 0) { /* Yes, we did. */ |
if(itlbmr) { /* Yes, we did. */ |
immu_stats.fetch_tlbhit++; |
TRACE("ITLB hit (virtaddr=%"PRIxADDR").\n", virtaddr); |
|
itlbtr = itlbmr + 128; |
|
/* Set LRUs */ |
for (i = 0; i < config.immu.nways; i++) { |
uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set]; |
if (lru & SPR_ITLBMR_LRU) { |
lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40); |
cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] = lru; |
} |
for(i = 0; i < config.immu.nways; i++, itlbmr_lru += (128 * 2)) { |
if(*itlbmr_lru & SPR_ITLBMR_LRU) |
*itlbmr_lru = (*itlbmr_lru & ~SPR_ITLBMR_LRU) | |
((*itlbmr_lru & SPR_ITLBMR_LRU) - 0x40); |
} |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU; |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] |= (config.immu.nsets - 1) << 6; |
|
/* This is not necessary `*itlbmr &= ~SPR_ITLBMR_LRU;' since SPR_DTLBMR_LRU |
* is always decremented and the number of sets is always a power of two and |
* as such lru_reload has all bits set that get touched during decrementing |
* SPR_DTLBMR_LRU */ |
*itlbmr |= config.immu.lru_reload; |
|
/* Check if page is cache inhibited */ |
insn_ci = (cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] & SPR_ITLBTR_CI) == SPR_ITLBTR_CI; |
insn_ci = *itlbtr & SPR_ITLBTR_CI; |
|
runtime.sim.mem_cycles += config.immu.hitdelay; |
|
/* Test for page fault */ |
if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) { |
if (!(cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] & SPR_ITLBTR_SXE)) |
if (!(*itlbtr & SPR_ITLBTR_SXE)) |
except_handle(EXCEPT_IPF, virtaddr); |
} else { |
if (!(cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] & SPR_ITLBTR_UXE)) |
if (!(*itlbtr & SPR_ITLBTR_UXE)) |
except_handle(EXCEPT_IPF, virtaddr); |
} |
|
ppn = cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] / config.immu.pagesize; |
return (ppn * config.immu.pagesize) + (virtaddr % config.immu.pagesize); |
TRACE("Returning physical address %"PRIxADDR"\n", |
(*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & |
(config.immu.page_offset_mask))); |
return (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & |
(config.immu.page_offset_mask)); |
} |
else { /* No, we didn't. */ |
immu_stats.fetch_tlbmiss++; |
|
/* No, we didn't. */ |
immu_stats.fetch_tlbmiss++; |
#if 0 |
for (i = 0; i < config.immu.nways; i++) |
if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_LRU) >> 6) < minlru) |
minway = i; |
|
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] &= ~SPR_ITLBMR_VPN; |
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= vpn << 12; |
for (i = 0; i < config.immu.nways; i++) { |
uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set]; |
if (lru & SPR_ITLBMR_LRU) { |
lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40); |
cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] = lru; |
} |
for (i = 0; i < config.immu.nways; i++) |
if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_LRU) >> 6) < minlru) |
minway = i; |
|
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] &= ~SPR_ITLBMR_VPN; |
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= vpn << 12; |
for (i = 0; i < config.immu.nways; i++) { |
uorreg_t lru = cpu_state.sprs[SPR_ITLBMR_BASE(i) + set]; |
if (lru & SPR_ITLBMR_LRU) { |
lru = (lru & ~SPR_ITLBMR_LRU) | ((lru & SPR_ITLBMR_LRU) - 0x40); |
cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] = lru; |
} |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU; |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] |= (config.immu.nsets - 1) << 6; |
} |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] &= ~SPR_ITLBMR_LRU; |
cpu_state.sprs[SPR_ITLBMR_BASE(way) + set] |= (config.immu.nsets - 1) << 6; |
|
/* 1 to 1 mapping */ |
cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] &= ~SPR_ITLBTR_PPN; |
cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] |= vpn << 12; |
/* 1 to 1 mapping */ |
cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] &= ~SPR_ITLBTR_PPN; |
cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] |= vpn << 12; |
|
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= SPR_ITLBMR_V; |
cpu_state.sprs[SPR_ITLBMR_BASE(minway) + set] |= SPR_ITLBMR_V; |
#endif |
|
/* if tlb refill implemented in HW */ |
/* return ((cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] & SPR_ITLBTR_PPN) >> 12) * config.immu.pagesize + (virtaddr % config.immu.pagesize); */ |
runtime.sim.mem_cycles += config.immu.missdelay; |
/* if tlb refill implemented in HW */ |
/* return ((cpu_state.sprs[SPR_ITLBTR_BASE(minway) + set] & SPR_ITLBTR_PPN) >> 12) * config.immu.pagesize + (virtaddr % config.immu.pagesize); */ |
runtime.sim.mem_cycles += config.immu.missdelay; |
|
except_handle(EXCEPT_ITLBMISS, virtaddr); |
return 0; |
} |
except_handle(EXCEPT_ITLBMISS, virtaddr); |
return 0; |
} |
|
/* DESC: try to find EA -> PA transaltion without changing |
148,10 → 180,9
*/ |
oraddr_t peek_into_itlb(oraddr_t virtaddr) |
{ |
int set, way = -1; |
int i; |
oraddr_t tagaddr; |
oraddr_t vpn, ppn; |
uorreg_t *itlbmr; |
uorreg_t *itlbtr; |
uorreg_t *itlbmr_lru; |
|
if (!(cpu_state.sprs[SPR_SR] & SPR_SR_IME) || |
!(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) { |
158,53 → 189,33
return(virtaddr); |
} |
|
/* Which set to check out? */ |
set = (virtaddr / config.immu.pagesize) % config.immu.nsets; |
tagaddr = (virtaddr / config.immu.pagesize) / config.immu.nsets; |
vpn = virtaddr / (config.immu.pagesize * config.immu.nsets); |
itlbmr = immu_find_tlbmr(virtaddr, &itlbmr_lru); |
|
/* Scan all ways and try to find a matching way. */ |
for (i = 0; i < config.immu.nways; i++) |
if (((cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] / (config.immu.pagesize * config.immu.nsets)) == vpn) && |
(cpu_state.sprs[SPR_ITLBMR_BASE(i) + set] & SPR_ITLBMR_V)) |
way = i; |
|
/* Did we find our tlb entry? */ |
if (way >= 0) { /* Yes, we did. */ |
|
if(itlbmr) { /* Yes, we did. */ |
itlbtr = itlbmr + 128; |
|
/* Test for page fault */ |
if (cpu_state.sprs[SPR_SR] & SPR_SR_SM) { |
if (!(cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] & SPR_ITLBTR_SXE)) { |
if (!(*itlbtr & SPR_ITLBTR_SXE)) { |
/* no luck, giving up */ |
return(0); |
} |
} else { |
if (!(cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] & SPR_ITLBTR_UXE)) { |
if (!(*itlbtr & SPR_ITLBTR_UXE)) { |
/* no luck, giving up */ |
return(0); |
} |
} |
|
ppn = cpu_state.sprs[SPR_ITLBTR_BASE(way) + set] / config.immu.pagesize; |
return (ppn * config.immu.pagesize) + (virtaddr % config.immu.pagesize); |
return (*itlbtr & SPR_ITLBTR_PPN) | (virtaddr & |
(config.immu.page_offset_mask)); |
} |
else { |
return(0); |
} |
|
ERR("should never have happened\n"); |
|
return(0); |
} |
|
|
oraddr_t immu_translate(oraddr_t virtaddr) |
{ |
oraddr_t phyaddr = immu_simulate_tlb(virtaddr); |
|
/* PRINTF("IMMU translate(%x) = %x\n", virtaddr, phyaddr);*/ |
return phyaddr; |
} |
|
void itlb_info(void) |
{ |
if (!(cpu_state.sprs[SPR_UPR] & SPR_UPR_IMP)) { |
/trunk/or1ksim/mmu/immu.h
21,3 → 21,4
oraddr_t immu_simulate_tlb(oraddr_t virtaddr); |
oraddr_t peek_into_itlb(oraddr_t virtaddr); |
void itlb_status(int start_set); |
void init_immu(void); |
/trunk/or1ksim/toplevel.c
68,7 → 68,7
#include "cuc.h" |
|
/* CVS revision number. */ |
const char rcsrev[] = "$Revision: 1.129 $"; |
const char rcsrev[] = "$Revision: 1.130 $"; |
|
inline void debug(int level, const char *format, ...) |
{ |
199,6 → 199,7
/* Initalizes all devices and sim */ |
void sim_init (void) |
{ |
init_immu(); |
init_labels(); |
init_breakpoints(); |
initstats(); |