Line 26... |
Line 26... |
#include <stdio.h>
|
#include <stdio.h>
|
#include <string.h>
|
#include <string.h>
|
#include <errno.h>
|
#include <errno.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_INTTYPES_H
|
|
#include <inttypes.h>
|
|
#endif
|
|
|
|
#include "port.h"
|
|
#include "arch.h"
|
#include "dcache_model.h"
|
#include "dcache_model.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "except.h"
|
#include "except.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
#include "stats.h"
|
#include "stats.h"
|
Line 39... |
Line 47... |
|
|
/* Data cache */
|
/* Data cache */
|
|
|
struct dc_set {
|
struct dc_set {
|
struct {
|
struct {
|
unsigned long line[MAX_DC_BLOCK_SIZE];
|
uint32_t line[MAX_DC_BLOCK_SIZE];
|
unsigned long tagaddr; /* tag address */
|
oraddr_t tagaddr; /* tag address */
|
int lru; /* least recently used */
|
int lru; /* least recently used */
|
} way[MAX_DC_WAYS];
|
} way[MAX_DC_WAYS];
|
} dc[MAX_DC_SETS];
|
} dc[MAX_DC_SETS];
|
|
|
void dc_info()
|
void dc_info()
|
Line 68... |
Line 76... |
- set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
|
- set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
|
ways unless they have reached 0
|
ways unless they have reached 0
|
- refill cache line
|
- refill cache line
|
*/
|
*/
|
|
|
unsigned long dc_simulate_read(unsigned long dataaddr, int width)
|
uint32_t dc_simulate_read(oraddr_t dataaddr, int width)
|
{
|
{
|
int set, way = -1;
|
int set, way = -1;
|
int i;
|
int i;
|
unsigned long tagaddr;
|
oraddr_t tagaddr;
|
unsigned long tmp;
|
uint32_t tmp;
|
|
|
if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
|
if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
|
(!testsprbits(SPR_SR, SPR_SR_DCE)) ||
|
(!testsprbits(SPR_SR, SPR_SR_DCE)) ||
|
data_ci) {
|
data_ci) {
|
if (width == 4)
|
if (width == 4)
|
tmp = evalsim_mem32(dataaddr);
|
tmp = evalsim_mem32(dataaddr);
|
else if (width == 2)
|
else if (width == 2)
|
tmp = (unsigned long)evalsim_mem16(dataaddr);
|
tmp = evalsim_mem16(dataaddr);
|
else if (width == 1)
|
else if (width == 1)
|
tmp = (unsigned long)evalsim_mem8(dataaddr);
|
tmp = evalsim_mem8(dataaddr);
|
|
|
if(!cur_area) {
|
if(!cur_area) {
|
if (width == 4)
|
if (width == 4)
|
printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", dataaddr);
|
printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
|
|
dataaddr);
|
else if (width == 2)
|
else if (width == 2)
|
printf("EXCEPTION: read out of memory (16-bit access to %.8lx)\n", dataaddr);
|
printf("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n",
|
|
dataaddr);
|
else if (width == 1)
|
else if (width == 1)
|
printf("EXCEPTION: read out of memory (8-bit access to %.8lx)\n", dataaddr);
|
printf("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n",
|
|
dataaddr);
|
except_handle(EXCEPT_BUSERR, cur_vadd);
|
except_handle(EXCEPT_BUSERR, cur_vadd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
if (!pending.valid && cur_area->log)
|
if (!pending.valid && cur_area->log)
|
fprintf (cur_area->log, "[%08lx] -> read %08lx\n", dataaddr, tmp);
|
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
|
|
tmp);
|
|
|
return tmp;
|
return tmp;
|
}
|
}
|
|
|
/* Which set to check out? */
|
/* Which set to check out? */
|
Line 125... |
Line 137... |
|
|
tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
if (width == 4)
|
if (width == 4)
|
return tmp;
|
return tmp;
|
else if (width == 2) {
|
else if (width == 2) {
|
tmp = (unsigned long)((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
|
tmp = ((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
|
return tmp;
|
return tmp;
|
}
|
}
|
else if (width == 1) {
|
else if (width == 1) {
|
tmp = (unsigned long)((tmp >> (8 * (3 - (dataaddr & 3)))) & 0xff);
|
tmp = ((tmp >> (8 * (3 - (dataaddr & 3)))) & 0xff);
|
return tmp;
|
return tmp;
|
}
|
}
|
} else { /* No, we didn't. */
|
} else { /* No, we didn't. */
|
int minlru = config.dc.ustates - 1;
|
int minlru = config.dc.ustates - 1;
|
int minway = 0;
|
int minway = 0;
|
Line 151... |
Line 163... |
dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
|
dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
|
evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
|
evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
|
if(!cur_area) {
|
if(!cur_area) {
|
dc[set].way[minway].tagaddr = -1;
|
dc[set].way[minway].tagaddr = -1;
|
dc[set].way[minway].lru = 0;
|
dc[set].way[minway].lru = 0;
|
printf("EXCEPTION: read out of memory (32-bit access to %.8lx)\n", dataaddr);
|
printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
|
|
dataaddr);
|
except_handle(EXCEPT_BUSERR, cur_vadd);
|
except_handle(EXCEPT_BUSERR, cur_vadd);
|
return 0;
|
return 0;
|
}
|
}
|
if (!pending.valid && cur_area->log)
|
if (!pending.valid && cur_area->log)
|
fprintf (cur_area->log, "[%08lx] -> read %08lx\n", dataaddr, tmp);
|
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
|
|
tmp);
|
}
|
}
|
|
|
dc[set].way[minway].tagaddr = tagaddr;
|
dc[set].way[minway].tagaddr = tagaddr;
|
for (i = 0; i < config.dc.nways; i++)
|
for (i = 0; i < config.dc.nways; i++)
|
if (dc[set].way[i].lru)
|
if (dc[set].way[i].lru)
|
Line 170... |
Line 184... |
|
|
tmp = dc[set].way[minway].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
tmp = dc[set].way[minway].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
if (width == 4)
|
if (width == 4)
|
return tmp;
|
return tmp;
|
else if (width == 2) {
|
else if (width == 2) {
|
tmp = (unsigned long)((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
|
tmp = (tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff;
|
return tmp;
|
return tmp;
|
}
|
}
|
else if (width == 1) {
|
else if (width == 1) {
|
tmp = (unsigned long)((tmp >> (8 * (3 - (dataaddr & 3)))) & 0xff);
|
tmp = (tmp >> (8 * (3 - (dataaddr & 3)))) & 0xff;
|
return tmp;
|
return tmp;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
Line 191... |
Line 205... |
- find lru way and entry and replace old tag with tag of the 'dataaddr'
|
- find lru way and entry and replace old tag with tag of the 'dataaddr'
|
- set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
|
- set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
|
ways unless they have reached 0
|
ways unless they have reached 0
|
*/
|
*/
|
|
|
void dc_simulate_write(unsigned long dataaddr, unsigned long data, int width)
|
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width)
|
{
|
{
|
int set, way = -1;
|
int set, way = -1;
|
int i;
|
int i;
|
unsigned long tagaddr;
|
oraddr_t tagaddr;
|
unsigned long tmp;
|
uint32_t tmp;
|
|
|
if (width == 4)
|
if (width == 4)
|
setsim_mem32(dataaddr, data);
|
setsim_mem32(dataaddr, data);
|
else if (width == 2)
|
else if (width == 2)
|
setsim_mem16(dataaddr, (unsigned short)data);
|
setsim_mem16(dataaddr, data);
|
else if (width == 1)
|
else if (width == 1)
|
setsim_mem8(dataaddr, (unsigned char)data);
|
setsim_mem8(dataaddr, data);
|
|
|
if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
|
if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
|
(!testsprbits(SPR_SR, SPR_SR_DCE)) ||
|
(!testsprbits(SPR_SR, SPR_SR_DCE)) ||
|
data_ci ||
|
data_ci ||
|
(!cur_area))
|
(!cur_area))
|
Line 235... |
Line 249... |
tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
|
if (width == 4)
|
if (width == 4)
|
tmp = data;
|
tmp = data;
|
else if (width == 2) {
|
else if (width == 2) {
|
tmp &= 0xffff << ((dataaddr & 2) ? 16 : 0);
|
tmp &= 0xffff << ((dataaddr & 2) ? 16 : 0);
|
tmp |= (unsigned long)(data & 0xffff) << ((dataaddr & 2) ? 0 : 16);
|
tmp |= (data & 0xffff) << ((dataaddr & 2) ? 0 : 16);
|
}
|
}
|
else if (width == 1) {
|
else if (width == 1) {
|
tmp &= ~(0xff << (8 * (3 - (dataaddr & 3))));
|
tmp &= ~(0xff << (8 * (3 - (dataaddr & 3))));
|
tmp |= (unsigned long)(data & 0xff) << (8 * (3 - (dataaddr & 3)));
|
tmp |= (data & 0xff) << (8 * (3 - (dataaddr & 3)));
|
}
|
}
|
dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2] = tmp;
|
dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2] = tmp;
|
}
|
}
|
else { /* No, we didn't. */
|
else { /* No, we didn't. */
|
int minlru = config.dc.ustates - 1;
|
int minlru = config.dc.ustates - 1;
|
Line 277... |
Line 291... |
/* First check if data is already in the cache and if it is:
|
/* First check if data is already in the cache and if it is:
|
- invalidate block if way isn't locked
|
- invalidate block if way isn't locked
|
otherwise don't do anything.
|
otherwise don't do anything.
|
*/
|
*/
|
|
|
void dc_inv(unsigned long dataaddr)
|
void dc_inv(oraddr_t dataaddr)
|
{
|
{
|
int set, way = -1;
|
int set, way = -1;
|
int i;
|
int i;
|
unsigned long tagaddr;
|
oraddr_t tagaddr;
|
|
|
if (!testsprbits(SPR_UPR, SPR_UPR_DCP))
|
if (!testsprbits(SPR_UPR, SPR_UPR_DCP))
|
return;
|
return;
|
|
|
/* Which set to check out? */
|
/* Which set to check out? */
|
Line 309... |
Line 323... |
dc[set].way[way].tagaddr = -1;
|
dc[set].way[way].tagaddr = -1;
|
dc[set].way[way].lru = 0;
|
dc[set].way[way].lru = 0;
|
}
|
}
|
}
|
}
|
|
|
inline void dc_clock()
|
void dc_clock()
|
{
|
{
|
unsigned long addr;
|
oraddr_t addr;
|
|
|
if ((addr = mfspr(SPR_DCBPR))) {
|
if ((addr = mfspr(SPR_DCBPR))) {
|
dc_simulate_read(addr, 4);
|
dc_simulate_read(addr, 4);
|
mtspr(SPR_DCBPR, 0);
|
mtspr(SPR_DCBPR, 0);
|
}
|
}
|