URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [cache/] [icache_model.c] - Rev 1308
Go to most recent revision | Compare with Previous | Blame | View Log
/* icache_model.c -- instruction cache simulation Copyright (C) 1999 Damjan Lampret, lampret@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Cache functions. At the moment this functions only simulate functionality of instruction caches and do not influence on fetche/decode/execute stages and timings. They are here only to verify performance of various cache configurations. */ #include <stdio.h> #include <string.h> #include <errno.h> #include <stdarg.h> #include "icache_model.h" #include "abstract.h" #include "except.h" #include "stats.h" #include "sim-config.h" #include "spr_defs.h" #include "sprs.h" #include "sim-config.h" extern struct dev_memarea *cur_area; struct ic_set { struct { unsigned long line[MAX_IC_BLOCK_SIZE]; unsigned long tagaddr; /* tag address */ int lru; /* least recently used */ } way[MAX_IC_WAYS]; } ic[MAX_IC_SETS]; void ic_info() { if (!testsprbits(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); } /* 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 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 ways unless they have reached 0 - refill cache line */ unsigned long ic_simulate_fetch(unsigned long fetchaddr) { int set, way = -1; int i; unsigned long tagaddr; unsigned long tmp; /* ICache simulation enabled/disabled. */ if ((!testsprbits(SPR_UPR, SPR_UPR_ICP)) || (!testsprbits(SPR_SR, SPR_SR_ICE)) || insn_ci) { tmp = evalsim_mem32(fetchaddr); if(!cur_area) { printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", fetchaddr); except_handle(EXCEPT_BUSERR, cur_vadd); return 0; } if (!pending.valid && cur_area->log) fprintf (cur_area->log, "[%08lx] -> read %08lx\n", fetchaddr, tmp); return tmp; } /* Which set to check out? */ set = (fetchaddr / config.ic.blocksize) % config.ic.nsets; tagaddr = (fetchaddr / config.ic.blocksize) / config.ic.nsets; /* Scan all ways and try to find a matching way. */ for (i = 0; i < config.ic.nways; i++) if (ic[set].way[i].tagaddr == tagaddr) way = i; /* Did we find our cached instruction? */ if (way >= 0) { /* Yes, we did. */ ic_stats.readhit++; for (i = 0; i < config.ic.nways; i++) if (ic[set].way[i].lru > ic[set].way[way].lru) ic[set].way[i].lru--; ic[set].way[way].lru = config.ic.ustates - 1; runtime.sim.mem_cycles += config.ic.hitdelay; return (ic[set].way[way].line[(fetchaddr & (config.ic.blocksize - 1)) >> 2]); } else { /* No, we didn't. */ int minlru = config.ic.ustates - 1; int minway = 0; ic_stats.readmiss++; for (i = 0; i < config.ic.nways; i++) { if (ic[set].way[i].lru < minlru) { minway = i; minlru = ic[set].way[i].lru; } } for (i = 0; i < (config.ic.blocksize); i += 4) { tmp = ic[set].way[minway].line[((fetchaddr + i) & (config.ic.blocksize - 1)) >> 2] = evalsim_mem32((fetchaddr & ~(config.ic.blocksize - 1)) + ((fetchaddr + i) & (config.ic.blocksize - 1))); if(!cur_area) { ic[set].way[minway].tagaddr = -1; ic[set].way[minway].lru = 0; printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", fetchaddr); except_handle(EXCEPT_BUSERR, cur_vadd); return 0; } if (!pending.valid && cur_area->log) fprintf (cur_area->log, "[%08lx] -> read %08lx\n", fetchaddr, tmp); } ic[set].way[minway].tagaddr = tagaddr; for (i = 0; i < config.ic.nways; i++) if (ic[set].way[i].lru) ic[set].way[i].lru--; ic[set].way[minway].lru = config.ic.ustates - 1; runtime.sim.mem_cycles += config.ic.missdelay; return (ic[set].way[minway].line[(fetchaddr & (config.ic.blocksize - 1)) >> 2]); } } /* First check if data is already in the cache and if it is: - invalidate block if way isn't locked otherwise don't do anything. */ void ic_inv(unsigned long dataaddr) { int set, way = -1; int i; unsigned long tagaddr; if (!testsprbits(SPR_UPR, SPR_UPR_ICP)) return; /* Which set to check out? */ set = (dataaddr / config.ic.blocksize) % config.ic.nsets; tagaddr = (dataaddr / config.ic.blocksize) / config.ic.nsets; if (!testsprbits(SPR_SR, SPR_SR_ICE)) { for (i = 0; i < config.ic.nways; i++) { ic[set].way[i].tagaddr = -1; ic[set].way[i].lru = 0; } return; } /* Scan all ways and try to find a matching way. */ for (i = 0; i < config.ic.nways; i++) if (ic[set].way[i].tagaddr == tagaddr) way = i; /* Did we find our cached data? */ if (way >= 0) { /* Yes, we did. */ ic[set].way[way].tagaddr = -1; ic[set].way[way].lru = 0; } } inline void ic_clock() { unsigned long addr; if ((addr = mfspr(SPR_ICBPR))) { ic_simulate_fetch(addr); mtspr(SPR_ICBPR, 0); } if ((addr = mfspr(SPR_ICBIR))) { ic_inv(addr); mtspr(SPR_ICBIR, 0); } if ((addr = mfspr(SPR_ICBLR))) { mtspr(SPR_ICBLR, 0); } }
Go to most recent revision | Compare with Previous | Blame | View Log