URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1485 to Rev 1486
- ↔ Reverse comparison
Rev 1485 → Rev 1486
/trunk/or1ksim/sim-config.h
24,7 → 24,6
|
/* Simulator configuration macros. Eventually this one will be a lot bigger. */ |
|
#define MAX_MEMORIES 16 /* Max. number of memory devices attached */ |
#define MAX_SBUF_LEN 256 /* Max. length of store buffer */ |
|
#define EXE_LOG_HARDWARE 0 /* Print out RTL states */ |
39,26 → 38,6
} tick; |
|
struct { |
int pattern; /* A user specified memory initialization pattern */ |
int random_seed; /* Initialize the memory with random values, starting with seed */ |
enum { |
MT_UNKNOWN, |
MT_PATTERN, |
MT_RANDOM |
} type; |
int nmemories; /* Number of attached memories */ |
struct { |
int ce; /* Which ce this memory is associated with */ |
unsigned long baseaddr; /* Start address of the memory */ |
unsigned long size; /* Memory size */ |
char name[STR_SIZE]; /* Memory type string */ |
char log[STR_SIZE]; /* Memory log filename */ |
int delayr; /* Read cycles */ |
int delayw; /* Write cycles */ |
} table[MAX_MEMORIES]; |
} memory; |
|
struct { |
int enabled; /* Whether IMMU is enabled */ |
int nways; /* Number of ITLB ways */ |
int nsets; /* Number of ITLB sets */ |
222,10 → 201,6
int supercycles; /* Superscalar cycles */ |
} cpu; |
|
struct { |
int random_seed; /* Initialize the memory with random values, starting with seed */ |
} memory; |
|
struct { /* Verification API, part of Advanced Core Verification */ |
int enabled; /* Whether is VAPI module enabled */ |
FILE *vapi_file; /* vapi file */ |
/trunk/or1ksim/sim.cfg
74,27 → 74,29
nmemories = <value> |
number of memory instances connected |
|
instance specific: |
baseaddr = <hex_value> |
memory start address |
baseaddr = <hex_value> |
memory start address |
|
size = <hex_value> |
memory size |
size = <hex_value> |
memory size |
|
name = "<string>" |
memory block name |
name = "<string>" |
memory block name |
|
ce = <value> |
chip enable index of the memory instance |
ce = <value> |
chip enable index of the memory instance |
|
delayr = <value> |
cycles, required for read access, -1 if instance does not support reading |
mc = <value> |
memory controller this memory is connected to |
|
delayw = <value> |
cycles, required for write access, -1 if instance does not support writing |
delayr = <value> |
cycles, required for read access, -1 if instance does not support reading |
|
log = "<filename>" |
filename, where to log memory accesses to, no log, if log command is not specified |
delayw = <value> |
cycles, required for write access, -1 if instance does not support writing |
|
log = "<filename>" |
filename, where to log memory accesses to, no log, if log command is not specified |
*/ |
|
|
104,34 → 106,43
pattern = 0x00 |
type = unknown /* Fastest */ |
|
name = "FLASH" |
ce = 0 |
mc = 0 |
baseaddr = 0xf0000000 |
size = 0x00800000 |
delayr = 10 |
delayw = -1 |
end |
|
nmemories = 3 |
device 0 |
name = "FLASH" |
ce = 0 |
baseaddr = 0xf0000000 |
size = 0x00800000 |
delayr = 10 |
delayw = -1 |
enddevice |
section memory |
/*random_seed = 12345 |
type = random*/ |
pattern = 0x00 |
type = unknown /* Fastest */ |
|
device 1 |
name = "RAM" |
ce = 1 |
baseaddr = 0x00000000 |
size = 0x00400000 |
delayr = 1 |
delayw = 2 |
enddevice |
name = "RAM" |
ce = 1 |
mc = 0 |
baseaddr = 0x00000000 |
size = 0x00400000 |
delayr = 1 |
delayw = 2 |
end |
|
device 2 |
name = "SRAM" |
ce = 2 |
baseaddr = 0x08000000 |
size = 0x00400000 |
delayr = 1 |
delayw = 2 |
enddevice |
section memory |
/*random_seed = 12345 |
type = random*/ |
pattern = 0x00 |
type = unknown /* Fastest */ |
|
name = "SRAM" |
mc = 0 |
ce = 2 |
baseaddr = 0x08000000 |
size = 0x00400000 |
delayr = 1 |
delayw = 2 |
end |
|
|
567,6 → 578,9
|
POC = <hex_value> |
Power On Configuration register |
|
index = <value> |
Index of this memory controller amongst all the memory controllers |
*/ |
|
section mc |
573,6 → 587,7
enabled = 1 |
baseaddr = 0x93000000 |
POC = 0x00000008 /* Power on configuration register */ |
index = 0 |
end |
|
|
/trunk/or1ksim/cpu/or32/dyn_rec_stubs.c
256,7 → 256,7
} |
|
static struct dev_memarea dummy_area = { |
delayr: 1, |
ops: { delayr: 1 }, |
}; |
|
struct dev_memarea *verify_memoryarea(oraddr_t addr) |
/trunk/or1ksim/cpu/or32/dyn_rec.c
507,6 → 507,20
} |
} |
|
/* Checks to see if a write happened to a recompiled page. If so marks it as |
* dirty */ |
void dyn_checkwrite(oraddr_t addr) |
{ |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
if((addr > 0x100) && (dp = find_dynd_page(addr)) && !dp->dirty) |
dirtyfy_page(dp); |
} |
|
static void ship_gprs_out_t(struct op_queue *opq, int end, unsigned int *reg_t) |
{ |
int i; |
915,7 → 929,7
for(j = 0; j < NUM_T_REGS; j++) |
opq->reg_t[j] = 32; /* Out-of-range registers */ |
|
dyn->delayr = -verify_memoryarea(rec_addr)->delayr; |
dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr; |
|
opq->num_ops = 0; |
opq->num_ops_param = 0; |
/trunk/or1ksim/cpu/or32/dyn_rec.h
43,12 → 43,12
void add_to_op_params(struct op_queue *opq, int end, unsigned long param); |
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len, |
unsigned int amount); |
void dirtyfy_page(struct dyn_page *dp); |
void init_dyn_recomp(void); |
void jump_dyn_code(oraddr_t addr); |
void run_sched_out_of_line(int add_normal); |
void recheck_immu(int got_en_dis); |
void enter_dyn_code(oraddr_t addr, struct dyn_page *dp); |
void dyn_checkwrite(oraddr_t addr); |
|
extern void *rec_stack_base; |
|
/trunk/or1ksim/cpu/common/abstract.c
1,5 → 1,6
/* abstract.c -- Abstract entities |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
67,16 → 68,32
struct dev_memarea *cur_area; |
|
/* Pointer to memory controller device descriptor. */ |
struct dev_memarea *mc_area = (struct dev_memarea *)0; |
struct dev_memarea *mc_area = NULL; |
|
/* These are set by mmu if cache inhibit bit is set for current acces. */ |
int data_ci, insn_ci; |
|
/* Virtual address of current access. */ |
oraddr_t cur_vadd; |
static oraddr_t cur_vadd; |
|
/* Read functions */ |
uint32_t eval_mem_32_inv(oraddr_t, void *); |
uint16_t eval_mem_16_inv(oraddr_t, void *); |
uint8_t eval_mem_8_inv(oraddr_t, void *); |
uint32_t eval_mem_32_inv_direct(oraddr_t, void *); |
uint16_t eval_mem_16_inv_direct(oraddr_t, void *); |
uint8_t eval_mem_8_inv_direct(oraddr_t, void *); |
|
/* Write functions */ |
void set_mem_32_inv(oraddr_t, uint32_t, void *); |
void set_mem_16_inv(oraddr_t, uint16_t, void *); |
void set_mem_8_inv(oraddr_t, uint8_t, void *); |
void set_mem_32_inv_direct(oraddr_t, uint32_t, void *); |
void set_mem_16_inv_direct(oraddr_t, uint16_t, void *); |
void set_mem_8_inv_direct(oraddr_t, uint8_t, void *); |
|
/* Calculates bit mask to fit the data */ |
unsigned int bit_mask (uint32_t data) { |
static unsigned int bit_mask (uint32_t data) { |
int i = 0; |
data--; |
while (data >> i) |
87,11 → 104,9
/* Register read and write function for a memory area. |
addr is inside the area, if addr & addr_mask == addr_compare |
(used also by peripheral devices like 16450 UART etc.) */ |
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare, |
uint32_t size, unsigned granularity, unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat) |
struct dev_memarea *register_memoryarea_mask(oraddr_t addr_mask, |
oraddr_t addr_compare, |
uint32_t size, unsigned mc_dev) |
{ |
struct dev_memarea **pptmp; |
unsigned int size_mask = bit_mask (size); |
98,9 → 113,8
int found_error = 0; |
addr_compare &= addr_mask; |
|
debug(5, "addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %08"PRIx32", gran %iB\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size, |
granularity); |
debug(5, "addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %08"PRIx32"\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size); |
/* Go to the end of the list. */ |
for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next) |
if ((addr_compare >= (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size) |
108,16 → 122,14
if (!found_error) { |
fprintf (stderr, "ERROR: Overlapping memory area(s):\n"); |
fprintf (stderr, "\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR |
", size %08"PRIx32", gran %iB\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size, |
granularity); |
", size %08"PRIx32"\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size); |
} |
found_error = 1; |
fprintf (stderr, "and\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR |
", size %08"PRIx32", gran %iB\n", |
", size %08"PRIx32"\n", |
(*pptmp)->addr_mask, (*pptmp)->addr_compare, |
(*pptmp)->addr_compare | (*pptmp)->size_mask, |
(*pptmp)->size, (*pptmp)->granularity); |
(*pptmp)->addr_compare | (*pptmp)->size_mask, (*pptmp)->size); |
} |
|
if (found_error) |
132,15 → 144,11
(*pptmp)->addr_compare = addr_compare; |
(*pptmp)->size = size; |
(*pptmp)->size_mask = size_mask; |
(*pptmp)->granularity = granularity; |
(*pptmp)->readfunc = readfunc; |
(*pptmp)->writefunc = writefunc; |
(*pptmp)->log = 0; |
(*pptmp)->delayr = 2; |
(*pptmp)->delayw = 2; |
(*pptmp)->priv_dat = dat; |
(*pptmp)->chip_select = -1; |
(*pptmp)->log = NULL; |
(*pptmp)->valid = 1; |
(*pptmp)->next = NULL; |
|
return *pptmp; |
} |
|
/* Register read and write function for a memory area. |
147,23 → 155,67
Memory areas should be aligned. Memory area is rounded up to |
fit the nearest 2^n aligment. |
(used also by peripheral devices like 16450 UART etc.) |
If mc_dev is 1, this means that this device will be checked first for match |
and will be accessed in case of overlaping memory spaces. |
If mc_dev is 1, this device will be checked first for a match |
and will be accessed in case of overlaping memory areas. |
Only one device can have this set to 1 (used for memory controller) */ |
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity, |
unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat) |
struct dev_memarea *reg_mem_area(oraddr_t addr, uint32_t size, unsigned mc_dev, |
struct mem_ops *ops) |
{ |
unsigned int size_mask = bit_mask (size); |
unsigned int addr_mask = ~size_mask; |
register_memoryarea_mask (addr_mask, addr & addr_mask, |
size_mask + 1, granularity, mc_dev, |
readfunc, writefunc, dat); |
struct dev_memarea *mem; |
|
mem = register_memoryarea_mask(addr_mask, addr & addr_mask, size_mask + 1, |
mc_dev); |
|
memcpy(&mem->ops, ops, sizeof(struct mem_ops)); |
memcpy(&mem->direct_ops, ops, sizeof(struct mem_ops)); |
|
if(!ops->readfunc32) { |
mem->ops.readfunc32 = eval_mem_32_inv; |
mem->direct_ops.readfunc32 = eval_mem_32_inv_direct; |
mem->direct_ops.read_dat32 = mem; |
} |
if(!ops->readfunc16) { |
mem->ops.readfunc16 = eval_mem_16_inv; |
mem->direct_ops.readfunc16 = eval_mem_16_inv_direct; |
mem->direct_ops.read_dat16 = mem; |
} |
if(!ops->readfunc8) { |
mem->ops.readfunc8 = eval_mem_8_inv; |
mem->direct_ops.readfunc8 = eval_mem_8_inv_direct; |
mem->direct_ops.read_dat8 = mem; |
} |
|
if(!ops->writefunc32) { |
mem->ops.writefunc32 = set_mem_32_inv; |
mem->direct_ops.writefunc32 = set_mem_32_inv_direct; |
mem->direct_ops.write_dat32 = mem; |
} |
if(!ops->writefunc16) { |
mem->ops.writefunc16 = set_mem_16_inv; |
mem->direct_ops.writefunc16 = set_mem_16_inv_direct; |
mem->direct_ops.write_dat16 = mem; |
} |
if(!ops->writefunc8) { |
mem->ops.writefunc8 = set_mem_8_inv; |
mem->direct_ops.writefunc8 = set_mem_8_inv_direct; |
mem->direct_ops.write_dat8 = mem; |
} |
|
if(!ops->writeprog) { |
mem->ops.writeprog = mem->ops.writefunc32; |
mem->ops.writeprog_dat = mem->ops.write_dat32; |
} |
|
if(ops->log) { |
if(!(mem->log = fopen(ops->log, "w"))) |
PRINTF("ERR: Unable to open %s to log memory acesses to\n", ops->log); |
} |
|
return mem; |
} |
|
|
/* Check if access is to registered area of memory. */ |
inline struct dev_memarea *verify_memoryarea(oraddr_t addr) |
{ |
185,155 → 237,166
return cur_area = NULL; |
} |
|
/* Finds the memory area for the address and adjust the read and write delays for it. */ |
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw) |
/* Sets the valid bit (Used only by memory controllers) */ |
void set_mem_valid(struct dev_memarea *mem, int valid) |
{ |
if (verify_memoryarea(memaddr)) { |
cur_area->delayr = delayr; |
cur_area->delayw = delayw; |
} |
mem->valid = valid; |
} |
|
/* for cpu accesses |
* |
* STATISTICS: check cpu/common/parse.c |
*/ |
inline uint32_t evalsim_mem32(oraddr_t memaddr) |
/* Adjusts the read and write delays for the memory area pointed to by mem. */ |
void adjust_rw_delay(struct dev_memarea *mem, int delayr, int delayw) |
{ |
return(evalsim_mem32_atomic(memaddr, 1)); |
mem->ops.delayr = delayr; |
mem->ops.delayw = delayw; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint32_t evalsim_mem32_void(oraddr_t memaddr) |
uint8_t eval_mem_8_inv(oraddr_t memaddr, void *dat) |
{ |
return(evalsim_mem32_atomic(memaddr, 0)); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
uint32_t evalsim_mem32_atomic(oraddr_t memaddr, int cpu_access) |
uint16_t eval_mem_16_inv(oraddr_t memaddr, void *dat) |
{ |
uint32_t temp = 0; |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 4: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
break; |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 24; |
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat) << 16; |
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat) << 8; |
temp |= cur_area->readfunc(memaddr + 3, cur_area->priv_dat); |
break; |
case 2: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 16; |
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat); |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr * (4 / cur_area->granularity); |
} |
return temp; |
uint32_t eval_mem_32_inv(oraddr_t memaddr, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
/* for cpu accesses */ |
inline uint16_t evalsim_mem16(oraddr_t memaddr) |
void set_mem_8_inv(oraddr_t memaddr, uint8_t val, void *dat) |
{ |
return(evalsim_mem16_atomic(memaddr, 1)); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint16_t evalsim_mem16_void(oraddr_t memaddr) |
void set_mem_16_inv(oraddr_t memaddr, uint16_t val, void *dat) |
{ |
return(evalsim_mem16_atomic(memaddr, 0)); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
uint16_t evalsim_mem16_atomic(oraddr_t memaddr, int cpu_access) |
void set_mem_32_inv(oraddr_t memaddr, uint32_t val, void *dat) |
{ |
uint32_t temp = 0; |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 8; |
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr * 2; |
break; |
case 2: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr; |
break; |
case 4: |
temp = evalsim_mem32_atomic (memaddr & ~UINT32_C(3), cpu_access); |
if (memaddr & 2) |
temp &= 0xffff; |
else |
temp >>= 16; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
} |
return temp; |
uint8_t eval_mem_8_inv_direct(oraddr_t memaddr, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 8-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
/* for cpu accesses */ |
inline uint8_t evalsim_mem8(oraddr_t memaddr) |
uint16_t eval_mem_16_inv_direct(oraddr_t memaddr, void *dat) |
{ |
return(evalsim_mem8_atomic(memaddr, 1)); |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 16-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint8_t evalsim_mem8_void(oraddr_t memaddr) |
uint32_t eval_mem_32_inv_direct(oraddr_t memaddr, void *dat) |
{ |
return(evalsim_mem8_atomic(memaddr, 0)); |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 32-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
uint8_t evalsim_mem8_atomic(oraddr_t memaddr, int cpu_access) |
void set_mem_8_inv_direct(oraddr_t memaddr, uint8_t val, void *dat) |
{ |
uint32_t temp = 0; |
struct dev_memarea *mem = dat; |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr; |
break; |
case 2: |
temp = evalsim_mem16_atomic (memaddr & ~ADDR_C(1), cpu_access); |
if (memaddr & 1) |
temp &= 0xff; |
else |
temp >>= 8; |
break; |
case 4: |
temp = evalsim_mem32_atomic (memaddr & ~ADDR_C(3), cpu_access); |
temp >>= 8 * (3 - (memaddr & 3)); |
temp &= 0xff; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
PRINTF("ERROR: Invalid 32-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
void set_mem_16_inv_direct(oraddr_t memaddr, uint16_t val, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 16-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
void set_mem_32_inv_direct(oraddr_t memaddr, uint32_t val, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 32-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem32 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint32_t evalsim_mem32(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc32(memaddr & mem->size_mask, mem->ops.read_dat32); |
} else { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
return temp; |
|
return 0; |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem16 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint16_t evalsim_mem16(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc16(memaddr & mem->size_mask, mem->ops.read_dat16); |
} else { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
|
return 0; |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem8 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint8_t evalsim_mem8(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc8(memaddr & mem->size_mask, mem->ops.read_dat8); |
} else { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
|
return 0; |
} |
|
/* Returns 32-bit values from mem array. Big endian version. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
341,6 → 404,7
uint32_t eval_mem32(oraddr_t memaddr,int* breakpoint) |
{ |
uint32_t temp; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_READ); |
353,26 → 417,18
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = dc_simulate_read(memaddr, 4); |
else { |
temp = evalsim_mem32(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
temp = dc_simulate_read(phys_memaddr, memaddr, 4); |
else |
temp = evalsim_mem32(phys_memaddr, memaddr); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
|
return temp; |
} |
|
383,31 → 439,31
uint32_t eval_direct32(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint32_t temp; |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
return 0; |
} |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = dc_simulate_read(memaddr, 4); |
return dc_simulate_read(phys_memaddr, memaddr, 4); |
else { |
temp = evalsim_mem32_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR |
") in eval_direct32()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc32(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat32); |
else |
PRINTF("ERR: 32-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
return temp; |
return 0; |
} |
|
|
418,15 → 474,15
uint32_t eval_insn(oraddr_t memaddr, int* breakpoint) |
{ |
uint32_t temp; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_FETCH); |
// memaddr = simulate_ic_mmu_fetch(memaddr); |
|
cur_vadd = memaddr; |
|
phys_memaddr = memaddr; |
#if !(DYNAMIC_EXECUTION) |
memaddr = immu_translate(memaddr); |
phys_memaddr = immu_translate(memaddr); |
|
if (except_pending) |
return 0; |
436,16 → 492,9
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); |
|
if (config.ic.enabled) |
temp = ic_simulate_fetch(memaddr); |
else { |
temp = evalsim_mem32(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
temp = ic_simulate_fetch(phys_memaddr, memaddr); |
else |
temp = evalsim_mem32(phys_memaddr, memaddr); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); |
461,8 → 510,6
uint32_t temp; |
int brk; |
|
cur_vadd = memaddr; |
|
if(through_mmu) |
memaddr = peek_into_itlb(memaddr); |
|
485,6 → 532,7
uint16_t eval_mem16(oraddr_t memaddr,int* breakpoint) |
{ |
uint16_t temp; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_16 | MPROF_READ); |
497,26 → 545,18
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (uint16_t)dc_simulate_read(memaddr, 2); |
else { |
temp = evalsim_mem16(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
temp = dc_simulate_read(phys_memaddr, memaddr, 2); |
else |
temp = evalsim_mem16(phys_memaddr, memaddr); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
|
return temp; |
} |
|
527,34 → 567,33
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint32_t temp; |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
return 0; |
} |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = dc_simulate_read(memaddr, 2); |
return dc_simulate_read(phys_memaddr, memaddr, 2); |
else { |
temp = evalsim_mem16_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR |
") in eval_direct16()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc16(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat16); |
else |
PRINTF("ERR: 16-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
return temp; |
return 0; |
} |
|
|
/* Returns 8-bit values from mem array. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
562,6 → 601,7
uint8_t eval_mem8(oraddr_t memaddr,int* breakpoint) |
{ |
uint8_t temp; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_READ); |
569,23 → 609,14
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (uint8_t)dc_simulate_read(memaddr, 1); |
else { |
temp = evalsim_mem8(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
temp = dc_simulate_read(phys_memaddr, memaddr, 1); |
else |
temp = evalsim_mem8(phys_memaddr, memaddr); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
599,195 → 630,94
uint8_t eval_direct8(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint8_t temp; |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = (unsigned char)dc_simulate_read(memaddr, 1); |
return dc_simulate_read(phys_memaddr, memaddr, 1); |
else { |
temp = evalsim_mem8_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR |
") in eval_direct8()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc8(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat8); |
else |
PRINTF("ERR: 8-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
return temp; |
} |
|
/* for cpu accesses */ |
inline void setsim_mem32(oraddr_t memaddr, uint32_t value) |
{ |
return(setsim_mem32_atomic(memaddr, value, 1)); |
return 0; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem32_void(oraddr_t memaddr, uint32_t value) |
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem32 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem32(oraddr_t memaddr, oraddr_t vaddr, uint32_t value) |
{ |
return(setsim_mem32_atomic(memaddr, value, 0)); |
} |
struct dev_memarea *mem; |
|
void setsim_mem32_atomic(oraddr_t memaddr, uint32_t value, int cpu_access) |
{ |
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 4: |
cur_area->writefunc(memaddr, value, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 1: |
cur_area->writefunc(memaddr , (value >> 24) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 2, (value >> 8) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 3, (value ) & 0xFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 4; |
break; |
case 2: |
cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 2, value & 0xFFFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 2; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc32(memaddr & mem->size_mask, value, mem->ops.write_dat32); |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
/* for cpu accesses */ |
inline void setsim_mem16(oraddr_t memaddr, uint16_t value) |
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem16 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem16(oraddr_t memaddr, oraddr_t vaddr, uint16_t value) |
{ |
return(setsim_mem16_atomic(memaddr, value, 1)); |
} |
struct dev_memarea *mem; |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem16_void(oraddr_t memaddr, uint16_t value) |
{ |
return(setsim_mem16_atomic(memaddr, value, 0)); |
} |
|
void setsim_mem16_atomic(oraddr_t memaddr, uint16_t value, int cpu_access) |
{ |
uint32_t temp; |
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
cur_area->writefunc(memaddr, (value >> 8) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 1, value & 0xFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 2; |
break; |
case 2: |
cur_area->writefunc(memaddr, value & 0xFFFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 4: |
temp = evalsim_mem32_void(memaddr & ~ADDR_C(3)); |
temp &= 0xffff << ((memaddr & 2) ? 16 : 0); |
temp |= (unsigned long)(value & 0xffff) << ((memaddr & 2) ? 0 : 16); |
setsim_mem32_atomic(memaddr & ~ADDR_C(3), temp, cpu_access); |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc16(memaddr & mem->size_mask, value, mem->ops.write_dat16); |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
|
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
/* for cpu accesses */ |
inline void setsim_mem8(oraddr_t memaddr, uint8_t value) |
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem8 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem8(oraddr_t memaddr, oraddr_t vaddr, uint8_t value) |
{ |
return(setsim_mem8_atomic(memaddr, value, 1)); |
} |
struct dev_memarea *mem; |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem8_void(oraddr_t memaddr, uint8_t value) |
{ |
return(setsim_mem8_atomic(memaddr, value, 0)); |
} |
|
void setsim_mem8_atomic(oraddr_t memaddr, uint8_t value, int cpu_access) |
{ |
uint32_t temp; |
if (verify_memoryarea(memaddr)) { |
switch (cur_area->granularity) { |
case 1: |
cur_area->writefunc(memaddr, value, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 2: |
temp = evalsim_mem16_void (memaddr & ~ADDR_C(1)); |
temp &= 0xff << ((memaddr & 1) ? 8 : 0); |
temp |= (unsigned short)(value & 0xff) << ((memaddr & 1) ? 0 : 8); |
setsim_mem16_atomic (memaddr & ~ADDR_C(1), temp, cpu_access); |
break; |
case 4: |
temp = evalsim_mem32_void (memaddr & ~ADDR_C(3)); |
temp &= ~(0xff << (8 * (3 - (memaddr & 3)))); |
temp |= (unsigned long)(value & 0xff) << (8 * (3 - (memaddr & 3))); |
setsim_mem32_atomic (memaddr & ~ADDR_C(3), temp, cpu_access); |
break; |
} |
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc8(memaddr & mem->size_mask, value, mem->ops.write_dat8); |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
|
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
800,6 → 730,8
*/ |
void set_mem32(oraddr_t memaddr, uint32_t value, int* breakpoint) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_WRITE); |
|
808,8 → 740,7
return; |
} |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
phys_memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) |
return; |
819,7 → 750,10
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 4); |
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 4); |
else |
setsim_mem32(phys_memaddr, memaddr, value); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %08"PRIx32"\n", memaddr, |
832,6 → 766,8
void set_direct32(oraddr_t memaddr, uint32_t value,int* breakpoint, |
int through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
838,22 → 774,25
return; |
} |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 1, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 1, through_dc); |
} |
|
if(through_dc) |
dc_simulate_write(memaddr, memaddr, value, 4); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc32(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat32); |
else |
PRINTF("ERR: 32-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR")\n", memaddr, phys_memaddr); |
} |
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 4); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %08"PRIx32"\n", |
memaddr, value); |
864,6 → 803,8
|
void set_mem16(oraddr_t memaddr, uint16_t value, int* breakpoint) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_16 | MPROF_WRITE); |
|
872,8 → 813,7
return; |
} |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
phys_memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) |
return; |
883,7 → 823,10
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 2); |
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 2); |
else |
setsim_mem16(phys_memaddr, memaddr, value); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %04"PRIx16"\n", memaddr, |
896,6 → 839,8
void set_direct16(oraddr_t memaddr, uint16_t value, int* breakpoint, |
int through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
902,20 → 847,24
return; |
} |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 2); |
if(through_dc) |
dc_simulate_write(memaddr, memaddr, value, 2); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc16(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat16); |
else |
PRINTF("ERR: 16-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %04"PRIx16"\n", |
923,14 → 872,16
} |
|
/* Set mem, 8-bit. */ |
|
void set_mem8(oraddr_t memaddr, uint8_t value, int* breakpoint) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_WRITE); |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
phys_memaddr = memaddr; |
|
phys_memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) return; |
|
939,7 → 890,10
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 1); |
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 1); |
else |
setsim_mem8(phys_memaddr, memaddr, value); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %02"PRIx8"\n", memaddr, |
952,21 → 906,27
void set_direct8(oraddr_t memaddr, uint8_t value, int* breakpoint, |
int through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
cur_vadd = memaddr; |
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 1); |
if(through_dc) |
dc_simulate_write(phys_memaddr, memaddr, value, 1); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc8(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat8); |
else |
PRINTF("ERR: 8-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %02"PRIx8"\n", |
974,6 → 934,26
} |
|
|
/* set_program32 - same as set_direct32, but it also writes to memory that is |
* non-writeable to the rest of the sim. Used to do program |
* loading. |
*/ |
void set_program32(oraddr_t memaddr, uint32_t value) |
{ |
struct dev_memarea *mem; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return; |
} |
|
if((mem = verify_memoryarea(memaddr))) { |
mem->ops.writeprog(memaddr & mem->size_mask, value, mem->ops.writeprog_dat); |
} else |
PRINTF("ERR: 32-bit program load out of memory area: %"PRIxADDR"\n", |
memaddr); |
} |
|
void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl) |
{ |
oraddr_t i, j; |
1021,110 → 1001,9
} |
} |
|
uint32_t simmem_read_word(oraddr_t addr, void *priv_dat) { |
return *(uint32_t *)(priv_dat + (addr & cur_area->size_mask)); |
} |
|
void simmem_write_word(oraddr_t addr, uint32_t value, void *priv_dat) { |
*(uint32_t *)(priv_dat + (addr & cur_area->size_mask)) = value; |
} |
|
uint32_t simmem_read_zero(oraddr_t addr, void *dat) { |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
void simmem_write_null(oraddr_t addr, uint32_t value, void *dat) { |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: memory write to 0x%"PRIxADDR", non-write memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
/* Initialize memory table from a config struct */ |
|
void init_memory_table () |
{ |
/* If nothing was defined, use default memory block */ |
if (config.memory.nmemories) { |
int i; |
for (i = 0; i < config.memory.nmemories; i++) { |
oraddr_t start = config.memory.table[i].baseaddr; |
uint32_t length = config.memory.table[i].size; |
char *type = config.memory.table[i].name; |
int rd = config.memory.table[i].delayr; |
int wd = config.memory.table[i].delayw; |
int ce = config.memory.table[i].ce; |
void *mem = malloc (length); |
|
if (config.sim.verbose) |
debug (1, "%"PRIxADDR" %08"PRIx32" (%"PRIi32" KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n", |
start, length, length >> 10, type, ce, rd, wd); |
|
if (!mem) { |
fprintf (stderr, "Failed to allocate sim memory. Aborting\n"); |
exit (-1); |
} |
|
register_memoryarea(start, length, 4, 0, &simmem_read_word, |
&simmem_write_word, mem); |
cur_area->chip_select = ce; |
cur_area->valid = 1; |
cur_area->delayw = wd; |
cur_area->delayr = rd; |
if (config.memory.table[i].log[0] != '\0') { |
if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL) |
fprintf (stderr, "WARNING: Cannot open '%s'.\n", |
config.memory.table[i].log); |
} else |
cur_area->log = NULL; |
} |
PRINTF ("\n"); |
} else { |
void *mem = malloc (DEFAULT_MEMORY_LEN); |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n"); |
|
if (!mem) { |
fprintf (stderr, "Failed to allocate sim memory. Aborting\n"); |
exit (-1); |
} |
|
register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0, |
&simmem_read_word, &simmem_write_word, mem); |
cur_area->chip_select = 0; |
cur_area->valid = 1; |
cur_area->delayw = 1; |
cur_area->delayr = 1; |
cur_area->log = NULL; |
} |
} |
|
/* Changes read/write memory in read/write only */ |
|
void lock_memory_table () |
{ |
struct dev_memarea *ptmp; |
|
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) { |
if (ptmp->delayr < 0 && ptmp->readfunc == &simmem_read_word) |
ptmp->readfunc = &simmem_read_zero; |
if (ptmp->delayw < 0 && ptmp->writefunc == &simmem_write_word) |
ptmp->writefunc = &simmem_write_null; |
|
/* If this mem area is not for memory chip under MC control |
then this area is valid all the time */ |
if (ptmp->readfunc != &simmem_read_word) { |
ptmp->valid = 1; |
ptmp->chip_select = -1; |
} |
} |
} |
|
/* Closes files, etc. */ |
|
void done_memory_table () |
void done_memory_table (void) |
{ |
struct dev_memarea *ptmp; |
|
1137,24 → 1016,23
|
/* Displays current memory configuration */ |
|
void memory_table_status () |
void memory_table_status (void) |
{ |
struct dev_memarea *ptmp; |
|
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) { |
PRINTF ("addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %"PRIx32 |
", gran %iB\n", |
PRINTF ("addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %"PRIx32"\n", |
ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size), |
ptmp->size, ptmp->granularity); |
ptmp->size); |
PRINTF ("\t"); |
if (ptmp->delayr >= 0) |
PRINTF ("read delay = %i cycles, ", ptmp->delayr); |
if (ptmp->ops.delayr >= 0) |
PRINTF ("read delay = %i cycles, ", ptmp->ops.delayr); |
else |
PRINTF ("reads not possible, "); |
|
if (ptmp->delayw >= 0) |
PRINTF ("write delay = %i cycles", ptmp->delayw); |
if (ptmp->ops.delayw >= 0) |
PRINTF ("write delay = %i cycles", ptmp->ops.delayw); |
else |
PRINTF ("writes not possible"); |
|
/trunk/or1ksim/cpu/common/abstract.h
42,28 → 42,54
oraddr_t insn_addr; |
}; |
|
struct mem_ops { |
/* Read functions */ |
uint32_t (*readfunc32)(oraddr_t, void *); |
uint16_t (*readfunc16)(oraddr_t, void *); |
uint8_t (*readfunc8)(oraddr_t, void *); |
|
/* Read functions' data */ |
void *read_dat8; |
void *read_dat16; |
void *read_dat32; |
|
/* Write functions */ |
void (*writefunc32)(oraddr_t, uint32_t, void *); |
void (*writefunc16)(oraddr_t, uint16_t, void *); |
void (*writefunc8)(oraddr_t, uint8_t, void *); |
|
/* Write functions' data */ |
void *write_dat8; |
void *write_dat16; |
void *write_dat32; |
|
/* Program load function. If you have unwritteable memory but you would like |
* it if a program would be loaded here, make sure to set this. If this is |
* not set, then writefunc32 will be called to load the program */ |
void (*writeprog)(oraddr_t, uint32_t, void *); |
void *writeprog_dat; |
|
/* Read/Write delays */ |
int delayr; |
int delayw; |
|
/* Name of log file */ |
const char *log; |
}; |
|
/* Memory regions assigned to devices */ |
struct dev_memarea { |
struct dev_memarea *next; |
/*unsigned long start; |
unsigned long end;*/ /* if start + size > end, this block is disabled; to enable it recalculate end addr. */ |
oraddr_t addr_mask; |
oraddr_t addr_compare; |
uint32_t size; |
uint32_t size_mask; /* Address mask, calculated out of size */ |
unsigned int granularity; /* how many bytes read/write accepts: 1/2/4 */ |
int delayr; /* Read delay */ |
int delayw; /* Write delay */ |
oraddr_t size_mask; /* Address mask, calculated out of size */ |
|
int chip_select; /* Needed by memory controller; specifies chip |
* select number for this memory area. */ |
int valid; /* This bit reflect the memory controler valid bit */ |
int valid; /* This bit reflects the memory controler valid bit */ |
FILE *log; /* log file if this device is to be logged, NULL otherwise */ |
|
uint32_t (*readfunc)(oraddr_t, void *); |
void (*writefunc)(oraddr_t, uint32_t, void *); |
/* private data */ |
void *priv_dat; |
struct mem_ops ops; |
struct mem_ops direct_ops; |
}; |
|
extern void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl); |
74,56 → 100,29
extern void set_mem16(oraddr_t memaddr, uint16_t value,int*); |
extern void set_mem8(oraddr_t memaddr, uint8_t value,int*); |
|
uint32_t evalsim_mem32(oraddr_t); |
uint16_t evalsim_mem16(oraddr_t); |
uint8_t evalsim_mem8(oraddr_t); |
uint32_t evalsim_mem32(oraddr_t, oraddr_t); |
uint16_t evalsim_mem16(oraddr_t, oraddr_t); |
uint8_t evalsim_mem8(oraddr_t, oraddr_t); |
|
uint32_t evalsim_mem32_atomic(oraddr_t, int); |
uint16_t evalsim_mem16_atomic(oraddr_t, int); |
uint8_t evalsim_mem8_atomic(oraddr_t, int); |
void setsim_mem32(oraddr_t, oraddr_t, uint32_t); |
void setsim_mem16(oraddr_t, oraddr_t, uint16_t); |
void setsim_mem8(oraddr_t, oraddr_t, uint8_t); |
|
void setsim_mem32(oraddr_t, uint32_t); |
void setsim_mem16(oraddr_t, uint16_t); |
void setsim_mem8(oraddr_t, uint8_t); |
|
void setsim_mem32_atomic(oraddr_t, uint32_t, int); |
void setsim_mem16_atomic(oraddr_t, uint16_t, int); |
void setsim_mem8_atomic(oraddr_t, uint8_t, int); |
|
void init_memory_table (); |
|
/* Changes read/write memory in read/write only */ |
void lock_memory_table (); |
|
/* Closes files, etc. */ |
void done_memory_table (); |
void done_memory_table (void); |
|
/* Displays current memory configuration */ |
void memory_table_status (); |
void memory_table_status (void); |
|
/* Register read and write function for a memory area. |
addr is inside the area, if addr & addr_mask == addr_compare |
(used also by peripheral devices like 16450 UART etc.) */ |
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare, |
uint32_t size, unsigned granularity, unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat); |
/* Register memory area */ |
struct dev_memarea *reg_mem_area(oraddr_t addr, uint32_t size, unsigned mc_dev, |
struct mem_ops *ops); |
|
/* Register read and write function for a memory area. |
Memory areas should be aligned. Memory area is rounded up to |
fit the nearest 2^n aligment. |
(used also by peripheral devices like 16450 UART etc.) |
If mc_dev is 1, this means that this device will be checked first for match |
and will be accessed in case in overlaping memory spaces. |
Only one device can have this set to 1 (used for memory controller) */ |
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity, |
unsigned mc_dev, uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat); |
/* Adjusts the read and write delays for the memory area pointed to by mem. */ |
void adjust_rw_delay(struct dev_memarea *mem, int delayr, int delayw); |
|
/* Finds the memory area for the address and adjust the read and write delays for it. */ |
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw); |
/* Sets the valid bit (Used only by memory controllers) */ |
void set_mem_valid(struct dev_memarea *mem, int valid); |
|
/* Check if access is to registered area of memory. */ |
struct dev_memarea *verify_memoryarea(oraddr_t addr); |
140,14 → 139,17
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu, int through_dc); |
uint32_t eval_direct32(oraddr_t addr, int *breakpoint, int through_mmu, int through_dc); |
|
void set_direct32(uint32_t addr, uint32_t value, int *breakpoint, int through_mmu, int through_dc); |
void set_direct8(oraddr_t, uint8_t, int *, int, int); |
void set_direct16(oraddr_t, uint16_t, int *, int, int); |
void set_direct32(oraddr_t, uint32_t, int *, int, int); |
|
/* Same as set_direct32, but it also writes to memory that is non-writeable to |
* the rest of the sim. Used to do program loading. */ |
void set_program32(oraddr_t memaddr, uint32_t value); |
|
/* Temporary variable to increase speed. */ |
extern struct dev_memarea *cur_area; |
|
/* Virtual address of current access. */ |
extern oraddr_t cur_vadd; |
|
/* These are set by mmu if cache inhibit bit is set for current acces. */ |
extern int data_ci, insn_ci; |
|
157,9 → 159,6
#define ULONGEST unsigned long long |
#endif /* ! LONGEST */ |
|
/* Instructions left to execute */ |
extern int cont_run; |
|
/* Returns the page that addr belongs to */ |
#define ADDR_PAGE(addr) ((addr) & ~(config.immu.pagesize - 1)) |
|
/trunk/or1ksim/cpu/common/parse.c
227,7 → 227,7
{ |
int vaddr = (!runtime.sim.filename) ? translate(address,breakpoint) : translate(freemem,breakpoint); |
|
setsim_mem32 (vaddr, insn); |
set_program32 (vaddr, insn); |
#if IMM_STATS |
check_insn (insn); |
#endif |
/trunk/or1ksim/cpu/or1k/sprs.c
69,7 → 69,11
/* Data cache simulateing stuff */ |
case SPR_DCBPR: |
if(value) { |
dc_simulate_read(value, 4); |
/* FIXME: The arch. manual says "DCBPR is written with the effective |
* address" which suggests it is written with a _virtual_ address, |
* but it seems that the cache sits behind the mmu. How is this |
* address translated then? */ |
dc_simulate_read(value, value, 4); |
cpu_state.sprs[SPR_DCBPR] = 0; |
} |
break; |
94,7 → 98,11
/* Instruction cache simulateing stuff */ |
case SPR_ICBPR: |
if(value) { |
ic_simulate_fetch(value); |
/* FIXME: The arch. manual says "ICBPR is written with the effective |
* address" which suggests it is written with a _virtual_ address, |
* but it seems that the cache sits behind the mmu. How is this |
* address translated then? */ |
ic_simulate_fetch(value, value); |
cpu_state.sprs[SPR_ICBPR] = 0; |
} |
break; |
/trunk/or1ksim/cache/icache_model.h
21,6 → 21,6
#define MAX_IC_WAYS 32 |
#define MAX_IC_BLOCK_SIZE 4 /* In words */ |
|
uint32_t ic_simulate_fetch(oraddr_t fetchaddr); |
uint32_t ic_simulate_fetch(oraddr_t fetchaddr, oraddr_t virt_addr); |
void ic_inv(oraddr_t dataaddr); |
void ic_info(); |
/trunk/or1ksim/cache/dcache_model.c
79,7 → 79,7
- refill cache line |
*/ |
|
uint32_t dc_simulate_read(oraddr_t dataaddr, int width) |
uint32_t dc_simulate_read(oraddr_t dataaddr, oraddr_t virt_addr, int width) |
{ |
int set, way = -1; |
int i; |
90,25 → 90,13
(!testsprbits(SPR_SR, SPR_SR_DCE)) || |
data_ci) { |
if (width == 4) |
tmp = evalsim_mem32(dataaddr); |
tmp = evalsim_mem32(dataaddr, virt_addr); |
else if (width == 2) |
tmp = evalsim_mem16(dataaddr); |
tmp = evalsim_mem16(dataaddr, virt_addr); |
else if (width == 1) |
tmp = evalsim_mem8(dataaddr); |
tmp = evalsim_mem8(dataaddr, virt_addr); |
|
if(!cur_area) { |
if (width == 4) |
printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
dataaddr); |
else if (width == 2) |
printf("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n", |
dataaddr); |
else if (width == 1) |
printf("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n", |
dataaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} else if (cur_area->log) |
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr, |
tmp); |
|
160,13 → 148,12
|
for (i = 0; i < (config.dc.blocksize); i += 4) { |
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))); |
/* 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((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~ADDR_C(3)) + i) & (config.dc.blocksize - 1)), 0); |
if(!cur_area) { |
dc[set].way[minway].tagaddr = -1; |
dc[set].way[minway].lru = 0; |
printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
dataaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr, |
205,7 → 192,8
ways unless they have reached 0 |
*/ |
|
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width) |
void dc_simulate_write(oraddr_t dataaddr, oraddr_t virt_addr, uint32_t data, |
int width) |
{ |
int set, way = -1; |
int i; |
213,11 → 201,11
uint32_t tmp; |
|
if (width == 4) |
setsim_mem32(dataaddr, data); |
setsim_mem32(dataaddr, virt_addr, data); |
else if (width == 2) |
setsim_mem16(dataaddr, data); |
setsim_mem16(dataaddr, virt_addr, data); |
else if (width == 1) |
setsim_mem8(dataaddr, data); |
setsim_mem8(dataaddr, virt_addr, data); |
|
if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) || |
(!testsprbits(SPR_SR, SPR_SR_DCE)) || |
269,7 → 257,8
|
for (i = 0; i < (config.dc.blocksize); i += 4) { |
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))); |
/* FIXME: Same comment as in dc_simulate_read */ |
evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)), 0); |
if(!cur_area) { |
dc[set].way[minway].tagaddr = -1; |
dc[set].way[minway].lru = 0; |
/trunk/or1ksim/cache/dcache_model.h
21,7 → 21,7
#define MAX_DC_WAYS 32 |
#define MAX_DC_BLOCK_SIZE 4 /* In words */ |
|
uint32_t dc_simulate_read(oraddr_t dataaddr, int width); |
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width); |
uint32_t dc_simulate_read(oraddr_t dataaddr, oraddr_t virt_addr, int width); |
void dc_simulate_write(oraddr_t dataaddr, oraddr_t virt_addr, uint32_t data, int width); |
void dc_info(); |
void dc_inv(oraddr_t dataaddr); |
/trunk/or1ksim/cache/icache_model.c
80,7 → 80,7
- refill cache line |
*/ |
|
uint32_t ic_simulate_fetch(oraddr_t fetchaddr) |
uint32_t ic_simulate_fetch(oraddr_t fetchaddr, oraddr_t virt_addr) |
{ |
int set, way = -1; |
int i; |
89,13 → 89,8
|
/* 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 %"PRIxADDR")\n", |
fetchaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} else if (cur_area->log) |
tmp = evalsim_mem32(fetchaddr, virt_addr); |
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", fetchaddr, |
tmp); |
return tmp; |
136,13 → 131,12
|
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))); |
/* 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 & ~(config.ic.blocksize - 1)) + ((fetchaddr + i) & (config.ic.blocksize - 1)), 0); |
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 %"PRIxADDR")\n", |
fetchaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", |
/trunk/or1ksim/cuc/bb.c
1228,8 → 1228,8
} |
} else { |
if (verify_memoryarea(buf[i].addr)) { |
if (buf[i].type & MPROF_WRITE) mscnt++, mssum += cur_area->delayw; |
else mlcnt++, mlsum += cur_area->delayr; |
if (buf[i].type & MPROF_WRITE) mscnt++, mssum += cur_area->ops.delayw; |
else mlcnt++, mlsum += cur_area->ops.delayr; |
} |
} |
} |
/trunk/or1ksim/testbench/default.cfg
23,24 → 23,28
pattern = 0x00 |
type = unknown /* Fastest */ |
|
nmemories = 2 |
device 0 |
name = "FLASH" |
ce = 0 |
baseaddr = 0xf0000000 |
size = 0x00200000 |
delayr = 10 |
delayw = -1 |
enddevice |
name = "FLASH" |
ce = 0 |
mc = 0 |
baseaddr = 0xf0000000 |
size = 0x00200000 |
delayr = 10 |
delayw = -1 |
end |
|
section memory |
/*random_seed = 12345 |
type = random*/ |
pattern = 0x00 |
type = unknown /* Fastest */ |
|
device 1 |
name = "RAM" |
ce = 1 |
baseaddr = 0x00000000 |
size = 0x00200000 |
delayr = 2 |
delayw = 4 |
enddevice |
name = "RAM" |
ce = 1 |
mc = 0 |
baseaddr = 0x00000000 |
size = 0x00200000 |
delayr = 2 |
delayw = 4 |
end |
|
section immu |
/trunk/or1ksim/peripheral/gpio.c
82,8 → 82,6
{ |
struct gpio_device *gpio = dat; |
|
addr -= gpio->baseaddr; |
|
switch( addr ) { |
case RGPIO_IN: return gpio->curr.in | gpio->curr.out; |
case RGPIO_OUT: return gpio->curr.out; |
104,8 → 102,6
{ |
struct gpio_device *gpio = dat; |
|
addr -= gpio->baseaddr; |
|
switch( addr ) { |
case RGPIO_IN: debug( 5, "GPIO: Cannot write to RGPIO_IN\n" ); break; |
case RGPIO_OUT: gpio->next.out = value; break; |
277,6 → 273,7
void gpio_sec_end(void *dat) |
{ |
struct gpio_device *gpio = dat; |
struct mem_ops ops; |
|
if(!gpio->enabled) { |
free(dat); |
283,8 → 280,19
return; |
} |
|
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = gpio_read32; |
ops.writefunc32 = gpio_write32; |
ops.write_dat32 = dat; |
ops.read_dat32 = dat; |
|
/* FIXME: Correct delays? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
/* Register memory range */ |
register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, 0, gpio_read32, gpio_write32, dat ); |
reg_mem_area( gpio->baseaddr, GPIO_ADDR_SPACE, 0, &ops ); |
|
reg_sim_reset(gpio_reset, dat); |
reg_sim_stat(gpio_status, dat); |
/trunk/or1ksim/peripheral/mc.c
43,33 → 43,62
#include "sim-config.h" |
#include "debug.h" |
|
extern struct dev_memarea *dev_list; |
struct mc_area { |
struct dev_memarea *mem; |
unsigned int cs; |
int mc; |
struct mc_area *next; |
}; |
|
void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) { |
struct dev_memarea *mem_dev = dev_list; |
struct mc { |
unsigned long csr; |
unsigned long poc; |
unsigned long ba_mask; |
unsigned long csc[N_CE]; |
unsigned long tms[N_CE]; |
oraddr_t baseaddr; |
int enabled; |
|
/* Index of this memory controler amongst all the memory controlers */ |
int index; |
/* List of memory devices under this mc's control */ |
struct mc_area *mc_areas; |
|
struct mc *next; |
}; |
|
static struct mc *mcs = NULL; |
|
/* List used to temporarily hold memory areas registered with the mc, while the |
* mc configureation has not been loaded */ |
static struct mc_area *mc_areas = NULL; |
|
void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) |
{ |
struct mc_area *cur = mc->mc_areas; |
|
while (mem_dev) { |
if (mem_dev->chip_select == cs) { |
mem_dev->addr_mask = mc->ba_mask << 22; |
mem_dev->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22; |
mem_dev->valid = (csc >> MC_CSC_EN_OFFSET) & 0x01; |
while (cur) { |
if (cur->cs == cs) { |
/* FIXME: No peripheral should _ever_ acess a dev_memarea structure |
* directly */ |
cur->mem->addr_mask = mc->ba_mask << 22; |
cur->mem->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22; |
set_mem_valid(cur->mem, (csc >> MC_CSC_EN_OFFSET) & 0x01); |
|
if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) { |
mem_dev->delayr = (tms & 0xff) + ((tms >> 8) & 0x0f); |
mem_dev->delayw = ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f); |
adjust_rw_delay(cur->mem, (tms & 0xff) + ((tms >> 8) & 0x0f), |
((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f)); |
} else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) { |
mem_dev->delayr = 3 + ((tms >> 4) & 0x03); |
mem_dev->delayw = 3 + ((tms >> 4) & 0x03); |
adjust_rw_delay(cur->mem, 3 + ((tms >> 4) & 0x03), |
3 + ((tms >> 4) & 0x03)); |
} else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) { |
mem_dev->delayr = 2; |
mem_dev->delayw = 2; |
adjust_rw_delay(cur->mem, 2, 2); |
} else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) { |
mem_dev->delayr = 2; |
mem_dev->delayw = 2; |
adjust_rw_delay(cur->mem, 2, 2); |
} |
return; |
} |
mem_dev = mem_dev->next; |
cur = cur->next; |
} |
} |
|
81,8 → 110,6
|
debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value); |
|
addr -= mc->baseaddr; |
|
switch (addr) { |
case MC_CSR: |
mc->csr = value; |
118,8 → 145,6
|
debug(5, "mc_read_word(%"PRIxADDR")", addr); |
|
addr -= mc->baseaddr; |
|
switch (addr) { |
case MC_CSR: |
value = mc->csr; |
149,7 → 174,7
void mc_reset(void *dat) |
{ |
struct mc *mc = dat; |
struct dev_memarea *mem_dev = dev_list; |
struct mc_area *cur, *prev, *tmp; |
|
PRINTF("Resetting memory controller.\n"); |
|
172,11 → 197,27
mc->tms[0] = MC_TMS_SYNC_VALID; |
} |
|
while (mem_dev) { |
mem_dev->valid = 0; |
mem_dev = mem_dev->next; |
/* Grab control over all the devices we are destined to control */ |
cur = mc_areas; |
prev = NULL; |
while (cur) { |
if (cur->mc == mc->index) { |
if (prev) prev->next = cur->next; |
else mc_areas = cur->next; |
prev = cur; |
tmp = cur->next; |
cur->next = mc->mc_areas; |
mc->mc_areas = cur; |
cur = tmp; |
} else { |
prev = cur; |
cur = cur->next; |
} |
} |
|
for (cur = mc->mc_areas; cur; cur = cur->next) |
set_mem_valid(cur->mem, 0); |
|
set_csc_tms (0, mc->csc[0], mc->tms[0], mc); |
} |
|
196,7 → 237,25
} |
} |
|
/*-----------------------------------------------------[ MC configuration }---*/ |
/*--------------------------------------------[ Peripheral<->MC interface ]---*/ |
/* Registers some memory to be under the memory controllers control */ |
void mc_reg_mem_area(struct dev_memarea *mem, unsigned int cs, int mc) |
{ |
struct mc_area *new; |
|
if(!(new = malloc(sizeof(struct mc_area)))) { |
fprintf(stderr, "Out-of-memory\n"); |
exit(-1); |
} |
new->cs = cs; |
new->mem = mem; |
new->mc = mc; |
|
new->next = mc_areas; |
mc_areas = new; |
} |
|
/*-----------------------------------------------------[ MC configuration ]---*/ |
void mc_enabled(union param_val val, void *dat) |
{ |
struct mc *mc = dat; |
215,6 → 274,12
mc->poc = val.int_val; |
} |
|
void mc_index(union param_val val, void *dat) |
{ |
struct mc *mc = dat; |
mc->index = val.int_val; |
} |
|
void *mc_sec_start(void) |
{ |
struct mc *new = malloc(sizeof(struct mc)); |
224,7 → 289,9
exit(-1); |
} |
|
new->index = 0; |
new->enabled = 0; |
new->mc_areas = NULL; |
|
return new; |
} |
232,6 → 299,7
void mc_sec_end(void *dat) |
{ |
struct mc *mc = dat; |
struct mem_ops ops; |
|
if(!mc->enabled) { |
free(dat); |
238,8 → 306,23
return; |
} |
|
register_memoryarea(mc->baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word, |
mc_write_word, dat); |
/* FIXME: Check to see that the index given to this mc is unique */ |
|
mc->next = mcs; |
mcs = mc; |
|
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = mc_read_word; |
ops.writefunc32 = mc_write_word; |
ops.write_dat32 = dat; |
ops.read_dat32 = dat; |
|
/* FIXME: Correct delays? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area(mc->baseaddr, MC_ADDR_SPACE, 1, &ops); |
reg_sim_reset(mc_reset, dat); |
reg_sim_stat(mc_status, dat); |
} |
251,4 → 334,5
reg_config_param(sec, "enabled", paramt_int, mc_enabled); |
reg_config_param(sec, "baseaddr", paramt_addr, mc_baseaddr); |
reg_config_param(sec, "POC", paramt_int, mc_POC); |
reg_config_param(sec, "index", paramt_int, mc_index); |
} |
/trunk/or1ksim/peripheral/mc.h
108,14 → 108,4
#define MC_TMS_SYNC_TRDV_OFFSET 0 |
#define MC_TMS_SYNC_TRDV_WIDTH 8 |
|
struct mc { |
unsigned long csr; |
unsigned long poc; |
unsigned long ba_mask; |
unsigned long csc[N_CE]; |
unsigned long tms[N_CE]; |
oraddr_t baseaddr; |
int enabled; |
}; |
|
#endif |
/trunk/or1ksim/peripheral/eth.c
648,7 → 648,6
uint32_t eth_read32( oraddr_t addr, void *dat ) |
{ |
struct eth_device *eth = dat; |
addr -= eth->baseaddr; |
|
switch( addr ) { |
case ETH_MODER: return eth->regs.moder; |
695,8 → 694,6
{ |
struct eth_device *eth = dat; |
|
addr -= eth->baseaddr; |
|
switch( addr ) { |
case ETH_MODER: |
|
889,6 → 886,7
void eth_sec_end(void *dat) |
{ |
struct eth_device *eth = dat; |
struct mem_ops ops; |
|
if(!eth->enabled) { |
free(dat); |
895,7 → 893,17
return; |
} |
|
register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, dat ); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = eth_read32; |
ops.writefunc32 = eth_write32; |
ops.read_dat32 = dat; |
ops.write_dat32 = dat; |
|
/* FIXME: Correct delay? */ |
ops.delayr = 2; |
ops.delayw = 2; |
reg_mem_area( eth->baseaddr, ETH_ADDR_SPACE, 0, &ops ); |
reg_sim_stat( eth_status, dat ); |
reg_sim_reset( eth_reset, dat ); |
} |
/trunk/or1ksim/peripheral/ps2kbd.c
134,8 → 134,7
void kbd_write8 (oraddr_t addr, uint32_t value, void *dat) |
{ |
struct kbd_state *kbd = dat; |
int a = (addr - kbd->baseaddr); |
switch (a) { |
switch (addr) { |
case KBD_CTRL: |
kbd->ccmd = value & 0xff; |
if (kbd->ccmd == KBD_CCMD_RCB) |
176,8 → 175,7
uint32_t kbd_read8 (oraddr_t addr, void *dat) |
{ |
struct kbd_state *kbd = dat; |
int a = (addr - kbd->baseaddr); |
switch (a) { |
switch (addr) { |
case KBD_CTRL: { |
unsigned long c = 0x0; |
if (kbd->kresp || kbd->buf_count) |
342,6 → 340,7
void kbd_sec_end(void *dat) |
{ |
struct kbd_state *kbd = dat; |
struct mem_ops ops; |
|
if(!kbd->enabled) { |
free(dat); |
348,7 → 347,18
return; |
} |
|
register_memoryarea(kbd->baseaddr, KBD_SPACE, 1, 0, kbd_read8, kbd_write8, dat); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc8 = kbd_read8; |
ops.writefunc8 = kbd_write8; |
ops.read_dat8 = dat; |
ops.write_dat8 = dat; |
|
/* FIXME: Correct delay? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area(kbd->baseaddr, KBD_SPACE, 0, &ops); |
reg_sim_reset(kbd_reset, dat); |
reg_sim_stat(kbd_info, dat); |
} |
/trunk/or1ksim/peripheral/fb.c
63,9 → 63,7
{ |
struct fb_state *fb = dat; |
|
oraddr_t a = (addr - fb->baseaddr); |
|
switch (a) { |
switch (addr) { |
case FB_CTRL: fb->ctrl = value; break; |
case FB_BUFADDR: change_buf_addr (fb, value); break; |
case FB_CAMBUFADDR: fb->cam_addr = value; break; |
74,11 → 72,11
fb->cameray = value / FB_SIZEX; |
break; |
default: |
a -= FB_PAL; |
a /= 4; |
if (a < 0 || a >= 256) { |
addr -= FB_PAL; |
addr /= 4; |
if (addr < 0 || addr >= 256) { |
fprintf (stderr, "Write out of palette buffer (0x%"PRIxADDR")!\n", addr); |
} else fb->pal[a] = value; |
} else fb->pal[addr] = value; |
break; |
} |
} |
88,9 → 86,7
{ |
struct fb_state *fb = dat; |
|
oraddr_t a = (addr - fb->baseaddr); |
|
switch (a) { |
switch (addr) { |
case FB_CTRL: |
return fb->ctrl & ~0xff000000| (fb->in_refresh ? 0x80000000 : 0) | ((unsigned long)(fb->refresh_count & 0x7f) << 24); |
break; |
98,12 → 94,12
case FB_CAMBUFADDR: return fb->cam_addr; break; |
case FB_CAMPOSADDR: return fb->camera_pos; break; |
default: |
a -= FB_PAL; |
a /= 4; |
if (a < 0 || a >= 256) { |
addr -= FB_PAL; |
addr /= 4; |
if (addr < 0 || addr >= 256) { |
fprintf (stderr, "Read out of palette buffer (0x%"PRIxADDR")!\n", addr); |
return 0; |
} else return fb->pal[a]; |
} else return fb->pal[addr]; |
} |
} |
|
368,6 → 364,7
void fb_sec_end(void *dat) |
{ |
struct fb_state *fb = dat; |
struct mem_ops ops; |
|
if(!fb->enabled) { |
free(dat); |
374,9 → 371,19
return; |
} |
|
if (fb->baseaddr) |
register_memoryarea(fb->baseaddr, FB_PAL + 256*4, 4, 0, fb_read32, fb_write32, dat); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = fb_read32; |
ops.writefunc32 = fb_write32; |
ops.write_dat32 = dat; |
ops.read_dat32 = dat; |
|
/* FIXME: Correct delay? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area(fb->baseaddr, FB_PAL + 256*4, 0, &ops); |
|
reg_sim_reset(fb_reset, dat); |
} |
|
/trunk/or1ksim/peripheral/dma.c
122,8 → 122,6
{ |
struct dma_controller *dma = dat; |
|
addr -= dma->baseaddr; |
|
if ( addr < DMA_CH_BASE ) { |
/* case of global (not per-channel) registers */ |
switch( addr ) { |
177,8 → 175,6
{ |
struct dma_controller *dma = dat; |
|
addr -= dma->baseaddr; |
|
/* case of global (not per-channel) registers */ |
if ( addr < DMA_CH_BASE ) { |
switch( addr ) { |
508,6 → 504,7
{ |
struct dma_controller *dma = dat; |
struct dma_controller *cur; |
struct mem_ops ops; |
|
if(!dma->enabled) { |
free(dat); |
514,7 → 511,18
return; |
} |
|
register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, 4, 0, dma_read32, dma_write32, dat ); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = dma_read32; |
ops.writefunc32 = dma_write32; |
ops.read_dat32 = dat; |
ops.write_dat32 = dat; |
|
/* FIXME: Correct delay?? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area( dma->baseaddr, DMA_ADDR_SPACE, 0, &ops ); |
reg_sim_reset( dma_reset, dat ); |
reg_sim_stat( dma_status, dat ); |
|
/trunk/or1ksim/peripheral/atahost.c
29,7 → 29,7
|
#include "port.h" |
#include "arch.h" |
/* get a prototype for 'register_memoryarea()', and 'adjust_rw_delay()' */ |
/* get a prototype for 'reg_mem_area()', and 'adjust_rw_delay()' */ |
#include "abstract.h" |
#include "sim-config.h" |
#include "sched.h" |
55,7 → 55,7
ata->regs.txb = 0; |
|
// inform simulator about new read/write delay timings |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
|
/* the reset bit in the control register 'ctrl' is set, reset connect ata-devices */ |
ata_devices_hw_reset(&ata->devices, 1); |
70,13 → 70,11
{ |
ata_host *ata = dat; |
|
addr -= ata->baseaddr; |
|
/* determine if ata_host or ata_device addressed */ |
if (is_ata_hostadr(addr)) |
{ |
// Accesses to internal register take 2cycles |
adjust_rw_delay( ata->baseaddr, 2, 2 ); |
adjust_rw_delay( ata->mem, 2, 2 ); |
|
switch( addr ) { |
case ATA_CTRL : |
120,13 → 118,13
if ( (addr & 0x7f) == ATA_DR) |
{ |
if (ata->devices.dev) |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); |
else |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); |
} |
else |
#endif |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
|
return ata_devices_read(&ata->devices, addr & 0x7f); |
} |
141,13 → 139,11
{ |
ata_host *ata = dat; |
|
addr -= ata->baseaddr; |
|
/* determine if ata_host or ata_device addressed */ |
if (is_ata_hostadr(addr)) |
{ |
// Accesses to internal register take 2cycles |
adjust_rw_delay( ata->baseaddr, 2, 2 ); |
adjust_rw_delay( ata->mem, 2, 2 ); |
|
switch( addr ) { |
case ATA_CTRL : |
209,13 → 205,13
if ( (addr & 0x7f) == ATA_DR) |
{ |
if (ata->devices.dev) |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); |
else |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); |
} |
else |
#endif |
adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); |
|
ata_devices_write(&ata->devices, addr & 0x7f, value); |
} |
340,6 → 336,7
void ata_sec_end(void *dat) |
{ |
ata_host *ata = dat; |
struct mem_ops ops; |
|
if(!ata->enabled) { |
free(dat); |
349,8 → 346,19
/* Connect ata_devices. */ |
ata_devices_init(&ata->devices); |
|
register_memoryarea(ata->baseaddr, ATA_ADDR_SPACE, 4, 0, ata_read32, ata_write32, dat); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = ata_read32; |
ops.read_dat32 = dat; |
ops.writefunc32 = ata_write32; |
ops.write_dat32 = dat; |
|
/* Delays will be readjusted later */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
ata->mem = reg_mem_area(ata->baseaddr, ATA_ADDR_SPACE, 0, &ops); |
|
reg_sim_reset(ata_reset, dat); |
reg_sim_stat(ata_status, dat); |
} |
/trunk/or1ksim/peripheral/memory.c
0,0 → 1,357
/* memory.c -- Generic memory model |
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. */ |
|
#include <stdio.h> |
#include <time.h> |
#include <string.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "abstract.h" |
#include "sim-config.h" |
|
struct mem_config { |
int ce; /* Which ce this memory is associated with */ |
int mc; /* Which mc this memory is connected to */ |
oraddr_t baseaddr; /* Start address of the memory */ |
unsigned int size; /* Memory size */ |
char *name; /* Memory type string */ |
char *log; /* Memory log filename */ |
int delayr; /* Read cycles */ |
int delayw; /* Write cycles */ |
|
void *mem; /* malloced memory for this memory */ |
|
int pattern; /* A user specified memory initialization |
* pattern */ |
int random_seed; /* Initialize the memory with random values, |
* starting with seed */ |
enum { |
MT_UNKNOWN, |
MT_PATTERN, |
MT_RANDOM |
} type; |
}; |
|
uint32_t simmem_read32(oraddr_t addr, void *dat) |
{ |
return *(uint32_t *)(dat + addr); |
} |
|
uint16_t simmem_read16(oraddr_t addr, void *dat) |
{ |
return *(uint16_t *)(dat + (addr ^ 2)); |
} |
|
uint8_t simmem_read8(oraddr_t addr, void *dat) |
{ |
return *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - addr & 3))); |
} |
|
void simmem_write32(oraddr_t addr, uint32_t value, void *dat) |
{ |
*(uint32_t *)(dat + addr) = value; |
} |
|
void simmem_write16(oraddr_t addr, uint16_t value, void *dat) |
{ |
*(uint16_t *)(dat + (addr ^ 2)) = value; |
} |
|
void simmem_write8(oraddr_t addr, uint8_t value, void *dat) |
{ |
*(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - addr & 3))) = value; |
} |
|
uint32_t simmem_read_zero32(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 32-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
uint16_t simmem_read_zero16(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 16-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
uint8_t simmem_read_zero8(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 8-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
void simmem_write_null32(oraddr_t addr, uint32_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 32-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void simmem_write_null16(oraddr_t addr, uint16_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 16-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void simmem_write_null8(oraddr_t addr, uint8_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 8-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void mem_reset(void *dat) |
{ |
struct mem_config *mem = dat; |
int seed; |
int i; |
uint8_t *mem_area = mem->mem; |
|
/* Initialize memory */ |
switch(mem->type) { |
case MT_RANDOM: |
if (mem->random_seed == -1) { |
seed = time(NULL); |
/* Print out the seed just in case we ever need to debug */ |
PRINTF("Seeding random generator with value %d\n", seed); |
} else |
seed = mem->random_seed; |
srandom(seed); |
|
for(i = 0; i < mem->size; i++, mem_area++) |
*mem_area = random() & 0xFF; |
break; |
case MT_PATTERN: |
for(i = 0; i < mem->size; i++, mem_area++) |
*mem_area = mem->pattern; |
break; |
case MT_UNKNOWN: |
break; |
default: |
fprintf(stderr, "Invalid memory configuration type.\n"); |
exit(1); |
} |
} |
|
/*-------------------------------------------------[ Memory configuration ]---*/ |
void memory_random_seed(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->random_seed = val.int_val; |
} |
|
void memory_pattern(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->pattern = val.int_val; |
} |
|
void memory_type(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
if(!strcmp(val.str_val, "unknown")) |
mem->type = MT_UNKNOWN; |
else if(!strcmp (val.str_val, "random")) |
mem->type = MT_RANDOM; |
else if(!strcmp (val.str_val, "pattern")) |
mem->type = MT_PATTERN; |
else if(!strcmp (val.str_val, "zero")) { |
mem->type = MT_PATTERN; |
mem->pattern = 0; |
} else { |
char tmp[200]; |
sprintf (tmp, "invalid memory type '%s'.\n", val.str_val); |
CONFIG_ERROR(tmp); |
} |
} |
|
void memory_ce(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->ce = val.int_val; |
} |
|
void memory_mc(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->mc = val.int_val; |
} |
|
void memory_baseaddr(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->baseaddr = val.addr_val; |
} |
|
void memory_size(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->size = val.int_val; |
} |
|
/* FIXME: Check use */ |
void memory_name(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->name = strdup(val.str_val); |
} |
|
void memory_log(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->log = strdup(val.str_val); |
} |
|
void memory_delayr(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->delayr = val.int_val; |
} |
|
void memory_delayw(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->delayw = val.int_val; |
} |
|
void *memory_sec_start(void) |
{ |
struct mem_config *mem = malloc(sizeof(struct mem_config)); |
|
if(!mem) { |
fprintf(stderr, "Memory Peripheral: Run out of memory\n"); |
exit(-1); |
} |
mem->size = 0; |
mem->log = NULL; |
mem->name = NULL; |
mem->delayr = 1; |
mem->delayw = 1; |
mem->random_seed = -1; |
mem->ce = -1; |
mem->mc = 0; |
|
return mem; |
} |
|
void memory_sec_end(void *dat) |
{ |
struct mem_config *mem = dat; |
struct dev_memarea *mema; |
|
struct mem_ops ops; |
|
if(!mem->size) { |
free(dat); |
return; |
} |
|
/* Round up to the next 32-bit boundry */ |
if(mem->size & 3) { |
mem->size &= ~3; |
mem->size += 4; |
} |
|
if(!(mem->mem = malloc(mem->size))) { |
fprintf(stderr, "Unable to allocate memory at %"PRIxADDR", length %i\n", |
mem->baseaddr, mem->size); |
exit(-1); |
} |
|
if(mem->delayr > 0) { |
ops.readfunc32 = simmem_read32; |
ops.readfunc16 = simmem_read16; |
ops.readfunc8 = simmem_read8; |
} else { |
ops.readfunc32 = simmem_read_zero32; |
ops.readfunc16 = simmem_read_zero16; |
ops.readfunc8 = simmem_read_zero8; |
} |
|
if(mem->delayw > 0) { |
ops.writefunc32 = simmem_write32; |
ops.writefunc16 = simmem_write16; |
ops.writefunc8 = simmem_write8; |
} else { |
ops.writefunc32 = simmem_write_null32; |
ops.writefunc16 = simmem_write_null16; |
ops.writefunc8 = simmem_write_null8; |
} |
|
ops.writeprog = simmem_write32; |
ops.writeprog_dat = mem->mem; |
|
ops.read_dat32 = mem->mem; |
ops.read_dat16 = mem->mem; |
ops.read_dat8 = mem->mem; |
|
ops.write_dat32 = mem->mem; |
ops.write_dat16 = mem->mem; |
ops.write_dat8 = mem->mem; |
|
ops.delayr = mem->delayr; |
ops.delayw = mem->delayw; |
|
ops.log = mem->log; |
|
mema = reg_mem_area(mem->baseaddr, mem->size, 0, &ops); |
|
/* Set valid */ |
/* FIXME: Should this be done during reset? */ |
set_mem_valid(mema, 1); |
|
if(mem->ce >= 0) |
mc_reg_mem_area(mema, mem->ce, mem->mc); |
|
reg_sim_reset(mem_reset, dat); |
} |
|
void reg_memory_sec(void) |
{ |
struct config_section *sec = reg_config_sec("memory", memory_sec_start, |
memory_sec_end); |
|
reg_config_param(sec, "random_seed", paramt_int, memory_random_seed); |
reg_config_param(sec, "pattern", paramt_int, memory_pattern); |
reg_config_param(sec, "type", paramt_word, memory_type); |
reg_config_param(sec, "ce", paramt_int, memory_ce); |
reg_config_param(sec, "mc", paramt_int, memory_mc); |
reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr); |
reg_config_param(sec, "size", paramt_int, memory_size); |
reg_config_param(sec, "name", paramt_str, memory_name); |
reg_config_param(sec, "log", paramt_str, memory_log); |
reg_config_param(sec, "delayr", paramt_int, memory_delayr); |
reg_config_param(sec, "delayw", paramt_int, memory_delayw); |
} |
|
/trunk/or1ksim/peripheral/atahost.h
108,6 → 108,9
/* Base address in memory */ |
oraddr_t baseaddr; |
|
/* Registered memory area */ |
struct dev_memarea *mem; |
|
/* Which IRQ to generate */ |
int irq; |
|
/trunk/or1ksim/peripheral/vga.c
55,8 → 55,6
{ |
struct vga_state *vga = dat; |
|
addr -= vga->baseaddr; |
|
switch (addr) { |
case VGA_CTRL: vga->ctrl = value; break; |
case VGA_STAT: vga->stat = value; break; |
83,8 → 81,6
{ |
struct vga_state *vga = dat; |
|
addr -= vga->baseaddr; |
|
switch (addr) { |
case VGA_CTRL: return vga->ctrl; |
case VGA_STAT: return vga->stat; |
286,6 → 282,7
void vga_sec_end(void *dat) |
{ |
struct vga_state *vga = dat; |
struct mem_ops ops; |
|
if(!vga->enabled) { |
free(dat); |
292,9 → 289,19
return; |
} |
|
if (vga->baseaddr) |
register_memoryarea(vga->baseaddr, VGA_ADDR_SPACE, 4, 0, vga_read32, vga_write32, dat); |
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = vga_read32; |
ops.writefunc32 = vga_write32; |
ops.write_dat32 = dat; |
ops.read_dat32 = dat; |
|
/* FIXME: Correct delay? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area(vga->baseaddr, VGA_ADDR_SPACE, 0, &ops); |
|
reg_sim_reset(vga_reset, dat); |
} |
|
/trunk/or1ksim/peripheral/16450.c
77,14 → 77,14
} |
|
/* Set a specific UART register with value. */ |
void uart_write_byte(oraddr_t addr, uint32_t value, void *dat) |
void uart_write_byte(oraddr_t addr, uint8_t value, void *dat) |
{ |
struct dev_16450 *uart = dat; |
|
TRACE("uart_write_byte(%"PRIxADDR",%02"PRIx32")\n", addr, value); |
TRACE("uart_write_byte(%"PRIxADDR",%02"PRIx8")\n", addr, value); |
|
if (uart->regs.lcr & UART_LCR_DLAB) { |
switch (addr % UART_ADDR_SPACE) { |
switch (addr) { |
case UART_DLL: |
uart->regs.dll = value; |
uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr); |
97,7 → 97,7
} |
} |
|
switch (addr % UART_ADDR_SPACE) { |
switch (addr) { |
case UART_TXBUF: |
if (uart->istat.txbuf_full < uart->fifo_len) { |
uart->istat.txbuf_full++; |
149,7 → 149,7
} |
|
/* Read a specific UART register. */ |
uint32_t uart_read_byte(oraddr_t addr, void *dat) |
uint8_t uart_read_byte(oraddr_t addr, void *dat) |
{ |
struct dev_16450 *uart = dat; |
uint8_t value = 0; |
157,7 → 157,7
TRACE("uart_read_byte(%"PRIxADDR")", addr); |
|
if (uart->regs.lcr & UART_LCR_DLAB) { |
switch (addr % UART_ADDR_SPACE) { |
switch (addr) { |
case UART_DLL: |
value = uart->regs.dll; |
TRACE("= %"PRIx8"\n", value); |
169,7 → 169,7
} |
} |
|
switch (addr % UART_ADDR_SPACE) { |
switch (addr) { |
case UART_RXBUF: |
{ /* Print out FIFO for debugging */ |
int i; |
589,7 → 589,7
if(channel_open(uart->channel) < 0) { |
WARN ("WARNING: problem with channel \"%s\" detected.\n", uart->channel_str); |
} else if (config.sim.verbose) |
PRINTF("UART at 0x%"PRIxADDR" uses ", uart->baseaddr); |
PRINTF("UART at 0x%"PRIxADDR"\n", uart->baseaddr); |
} else { |
WARN ("WARNING: UART at %"PRIxADDR" has no vapi nor channel specified\n", |
uart->baseaddr); |
761,13 → 761,26
void uart_sec_end(void *dat) |
{ |
struct dev_16450 *uart = dat; |
struct mem_ops ops; |
|
if(!uart->enabled) { |
free(dat); |
return; |
} |
register_memoryarea(uart->baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, |
uart_write_byte, dat); |
|
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc8 = uart_read_byte; |
ops.writefunc8 = uart_write_byte; |
ops.read_dat8 = dat; |
ops.write_dat8 = dat; |
|
/* FIXME: What should these be? */ |
ops.delayr = 2; |
ops.delayw = 2; |
|
reg_mem_area(uart->baseaddr, UART_ADDR_SPACE, 0, &ops); |
|
reg_sim_reset(uart_reset, dat); |
reg_sim_stat(uart_status, dat); |
} |
/trunk/or1ksim/peripheral/Makefile.am
33,4 → 33,5
ps2kbd.c \ |
atahost.c \ |
atadevice.c \ |
atadevice_cmdi.c |
atadevice_cmdi.c \ |
memory.c |
/trunk/or1ksim/toplevel.c
68,7 → 68,7
#include "cuc.h" |
|
/* CVS revision number. */ |
const char rcsrev[] = "$Revision: 1.126 $"; |
const char rcsrev[] = "$Revision: 1.127 $"; |
|
inline void debug(int level, const char *format, ...) |
{ |
185,10 → 185,8
du_reset (); |
|
/* Make sure that runtime.sim.iprompt is the first thing to get checked */ |
SCHED_ADD(check_int, NULL, 0); |
SCHED_ADD(check_int, NULL, 1); |
|
lock_memory_table (); |
|
/* FIXME: Lame-ass way to get runtime.sim.mem_cycles not going into overly |
* negative numbers. This happens because parse.c uses setsim_mem32 to load |
* the program but set_mem32 calls dc_simulate_write, which inturn calls |
199,9 → 197,8
} |
|
/* Initalizes all devices and sim */ |
void sim_init () |
void sim_init (void) |
{ |
init_memory_table (); |
init_labels(); |
init_breakpoints(); |
initstats(); |
248,37 → 245,6
} |
} |
|
/* Initialize memory */ |
{ |
extern struct dev_memarea *dev_list; |
struct dev_memarea *area; |
int i; |
if (config.memory.type == MT_RANDOM) { |
unsigned int val = 0; |
|
if (config.memory.random_seed == -1) { |
runtime.memory.random_seed = time(NULL); |
/* Print out the seed just in case we ever need to debug */ |
PRINTF("Seeding random generator with value %d\n", config.memory.random_seed); |
} else |
runtime.memory.random_seed = config.memory.random_seed; |
srandom(runtime.memory.random_seed); |
|
for (area = dev_list; area; area = area->next) |
for(i = 0; i < area->size; i++) { |
val = random(); |
setsim_mem8(i + area->addr_compare, val & 0xFF); |
} |
} else if(config.memory.type == MT_PATTERN) { |
for (area = dev_list; area; area = area->next) |
for(i = 0; i < area->size; i++) |
setsim_mem8(i + area->addr_compare, config.memory.pattern); |
} else if (config.memory.type != MT_UNKNOWN) { |
fprintf(stderr, "Invalid memory configuration type.\n"); |
exit(1); |
} |
} |
|
if(runtime.sim.filename) { |
unsigned long endaddr = 0xFFFFFFFF; |
endaddr = loadcode(runtime.sim.filename, 0, 0); /* MM170901 always load at address zero. */ |
/trunk/or1ksim/sim-config.c
90,13 → 90,6
else config.sim.system_kfreq = INT_MAX; |
if (config.sim.system_kfreq <= 0) config.sim.system_kfreq = 1; |
|
/* Memory */ |
config.memory.type = MT_UNKNOWN; |
config.memory.pattern = 0; |
config.memory.random_seed = -1; /* Generate new seed */ |
for (i = 0; i < MAX_MEMORIES; i++) |
config.memory.table[i].ce = -1; /* memory is disabled by default */ |
|
/* IMMU & DMMU*/ |
config.immu.enabled = 0; |
config.immu.hitdelay = 1; |
420,106 → 413,6
reg_config_param(sec, "stdout", paramt_str, sim_stdout); |
} |
|
/*-------------------------------------------------[ Memory configuration ]---*/ |
void memory_random_seed(union param_val val, void *dat) { |
config.memory.random_seed = val.int_val; |
} |
|
void memory_pattern(union param_val val, void *dat) { |
config.memory.pattern = val.int_val; |
} |
|
void memory_nmemories (union param_val val, void *dat) { |
if (val.int_val >= 0 && val.int_val < MAX_MEMORIES) |
config.memory.nmemories = val.int_val; |
else |
CONFIG_ERROR("invalid number of devices."); |
} |
|
void memory_type (union param_val val, void *dat) { |
if (strcmp (val.str_val, "unknown") == 0) |
config.memory.type = MT_UNKNOWN; |
else if (strcmp (val.str_val, "random") == 0) |
config.memory.type = MT_RANDOM; |
else if (strcmp (val.str_val, "pattern") == 0) |
config.memory.type = MT_PATTERN; |
else if (strcmp (val.str_val, "zero") == 0) { |
config.memory.type = MT_PATTERN; |
config.memory.pattern = 0; |
} else { |
char tmp[200]; |
sprintf (tmp, "invalid memory type '%s'.\n", val.str_val); |
CONFIG_ERROR(tmp); |
} |
} |
|
void memory_ce (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
config.memory.table[current_device].ce = val.int_val; |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_baseaddr (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
config.memory.table[current_device].baseaddr = val.addr_val; |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_size (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
config.memory.table[current_device].size = val.int_val; |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_name (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
strcpy (config.memory.table[current_device].name, val.str_val); |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_log (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
strcpy (config.memory.table[current_device].log, val.str_val); |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_delayr (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
config.memory.table[current_device].delayr = val.int_val; |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void memory_delayw (union param_val val, void *dat) { |
if (current_device >= 0 && current_device < config.memory.nmemories) |
config.memory.table[current_device].delayw = val.int_val; |
else |
CONFIG_ERROR("invalid device number."); |
} |
|
void reg_memory_sec(void) { |
struct config_section *sec = reg_config_sec("memory", NULL, NULL); |
|
reg_config_param(sec, "random_seed", paramt_int, memory_random_seed); |
reg_config_param(sec, "pattern", paramt_int, memory_pattern); |
reg_config_param(sec, "type", paramt_word, memory_type); |
reg_config_param(sec, "nmemories", paramt_int, memory_nmemories); |
reg_config_param(sec, "device", paramt_int, change_device); |
reg_config_param(sec, "enddevice", paramt_none, end_device); |
reg_config_param(sec, "ce", paramt_int, memory_ce); |
reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr); |
reg_config_param(sec, "size", paramt_int, memory_size); |
reg_config_param(sec, "name", paramt_str, memory_name); |
reg_config_param(sec, "log", paramt_str, memory_log); |
reg_config_param(sec, "delayr", paramt_int, memory_delayr); |
reg_config_param(sec, "delayw", paramt_int, memory_delayw); |
} |
|
/*----------------------------------------------------[ CPU configuration ]---*/ |
void cpu_ver (union param_val val, void *dat) { |
config.cpu.ver = val.int_val; |