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

powered by: WebSVN 2.1.0

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