OpenCores
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;

powered by: WebSVN 2.1.0

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