X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=sim%2Fucsim%2Fsim.src%2Fmem.cc;h=7d9a780fdc15ff321c9e40a6e739a28eeca0aa30;hb=f27da39dbcab5678aca6d8462f1cc37a643f37e9;hp=f47137aaeab01df75949ba0cf10b83f657e58a86;hpb=7fe573ea83f6e0762dc73bc493f15fa2a8f6273d;p=fw%2Fsdcc diff --git a/sim/ucsim/sim.src/mem.cc b/sim/ucsim/sim.src/mem.cc index f47137aa..7d9a780f 100644 --- a/sim/ucsim/sim.src/mem.cc +++ b/sim/ucsim/sim.src/mem.cc @@ -7,22 +7,24 @@ * */ -/* This file is part of microcontroller simulator: ucsim. - -UCSIM 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. - -UCSIM 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 UCSIM; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +/* + This file is part of microcontroller simulator: ucsim. + + UCSIM 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. + + UCSIM 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 UCSIM; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ /*@1@*/ #include @@ -46,141 +48,31 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* - * Memory location handled specially by a hw element + * 3rd version of memory system */ -/*cl_memloc::cl_memloc(t_addr addr): +cl_memory::cl_memory(char *id, t_addr asize, int awidth): cl_base() { - address= addr; - hws= new cl_list(2, 2); - hws->init(); -}*/ - -/*cl_memloc::~cl_memloc(void) -{ - hws->disconn_all(); - delete hws; -}*/ - -/*ulong -cl_memloc::read(class cl_mem *mem) -{ - uchar ret= 0; - class cl_hw *hw; - - if (!hws || - hws->count == 0) - return(ret); - if ((hw= (class cl_hw *)(hws->at(0)))) - ret= hw->read(mem, address); - return(ret); -}*/ - -/*void -cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val) -{ - class cl_hw *hw; - int i; - - if (!hws) - return; - for (i= 0; i < hws->count; i++) - { - hw= (class cl_hw *)hws->at(0); - hw->write(mem, addr, val); - } -}*/ - - -/* Sorted collection of memory locations */ - -/*cl_memloc_coll::cl_memloc_coll(void): - cl_sorted_list(2, 2) -{ - Duplicates= DD_FALSE; -}*/ - -/*void * -cl_memloc_coll::key_of(void *item) -{ - return(&(((class cl_memloc *)item)->address)); -}*/ - -/*int -cl_memloc_coll::compare(void *key1, void *key2) -{ - if (*(long*)key1 > *(long*)key2) - return(1); - else - if (*(long*)key1 < *(long*)key2) - return(-1); - else - return(0); -}*/ - -/*class cl_memloc * -cl_memloc_coll::get_loc(t_addr address) -{ - t_index i; - - if (search(&address, i)) - return((class cl_memloc*)(at(i))); - return(0); -}*/ - - -/* - * Memory - ****************************************************************************** - */ - -cl_mem::cl_mem(enum mem_class atype, char *aclass_name, - t_addr asize, int awidth, class cl_uc *auc): - cl_guiobj() -{ - int i; - - uc= auc; - type= atype; - class_name= aclass_name; - width= awidth; size= asize; - mem= 0; - for (i= width, mask= 0; i; i--) - mask= (mask<<1) | 1; - if (width == 0 || - size == 0) - mem= 0; - else if (width <= 8) - mem= (TYPE_UBYTE *)malloc(size); - else if (width <= 16) - mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD)); - else - mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD)); - //read_locs= new cl_memloc_coll(); - //write_locs= new cl_memloc_coll(); - dump_finished= 0; + set_name(id); addr_format= data_format= 0; + width= awidth; + start_address= 0; + uc= 0; } -cl_mem::~cl_mem(void) +cl_memory::~cl_memory(void) { - if (mem) - free(mem); if (addr_format) free(addr_format); if (data_format) free(data_format); - //delete read_locs; - //delete write_locs; } int -cl_mem::init(void) +cl_memory::init(void) { - t_addr i; - addr_format= (char *)malloc(10); sprintf(addr_format, "0x%%0%dx", size-1<=0xf?1: @@ -191,160 +83,101 @@ cl_mem::init(void) (size-1<=0xffffff?6:12)))))); data_format= (char *)malloc(10); sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0)); - - for (i= 0; i < size; i++) - set(i, (type==MEM_ROM)?(-1):0); + data_mask= 1; + int w= width; + for (--w; w; w--) + { + data_mask<<= 1; + data_mask|= 1; + } + dump_finished= start_address; return(0); } -char * -cl_mem::id_string(void) -{ - char *s= get_id_string(mem_ids, type); - - return(s?s:(char*)"NONE"); -} -t_mem -cl_mem::read(t_addr addr) +bool +cl_memory::valid_address(t_addr addr) { - //class cl_memloc *loc; - - if (addr >= size) - { - //FIXME - fprintf(stderr, "Address 0x%06"_A_"x is over 0x%06"_A_"x\n", addr, size); - return(0); - } - /*if ((loc= read_locs->get_loc(addr))) - return(loc->read(this));*/ - if (width <= 8) - return((((TYPE_UBYTE*)mem)[addr])&mask); - else if (width <= 16) - return((((TYPE_UWORD*)mem)[addr])&mask); - else - return((((TYPE_UDWORD*)mem)[addr])&mask); + return(addr >= start_address && + addr < start_address+size); } -t_mem -cl_mem::get(t_addr addr) +t_addr +cl_memory::inc_address(t_addr addr, int val) { - if (addr >= size) - return(0); - if (width <= 8) - return((((TYPE_UBYTE*)mem)[addr])&mask); - else if (width <= 16) - return((((TYPE_UWORD*)mem)[addr])&mask); - else - return((((TYPE_UDWORD*)mem)[addr])&mask); + if (!start_address) + return(((signed)addr+val)%size); + addr-= start_address; + addr+= val; + addr%= size; + addr+= start_address; + return(addr); } - -/* - * Modify memory location - */ - -/* Write calls callbacks of HW elements */ - -t_mem -cl_mem::write(t_addr addr, t_mem val) +t_addr +cl_memory::inc_address(t_addr addr) { - /* class cl_memloc *loc; - - if (addr >= size) - return; - if ((loc= write_locs->get_loc(addr))) - loc->write(this, addr, val); - if (width <= 8) - ((TYPE_UBYTE*)mem)[addr]= (*val)&mask; - else if (width <= 16) - ((TYPE_UWORD*)mem)[addr]= (*val)&mask; - else - ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;*/ - fprintf(stderr, "FIXME cl_mem::write(0x%06"_A_"x, 0x%04"_M_"x)\n", - addr, val); - return(0); + if (!start_address) + return(((signed)addr+1)%size); + addr-= start_address; + addr++; + addr%= size; + addr+= start_address; + return(addr); } -/* Set doesn't call callbacks */ - -void -cl_mem::set(t_addr addr, t_mem val) +t_addr +cl_memory::validate_address(t_addr addr) { - if (addr >= size) - return; - if (width <= 8) - ((TYPE_UBYTE*)mem)[addr]= val&mask; - else if (width <= 16) - ((TYPE_UWORD*)mem)[addr]= val&mask; - else - ((TYPE_UDWORD*)mem)[addr]= val&mask; + while (addr < start_address) + addr+= size; + if (addr > start_address+size) + { + addr-= start_address; + addr%= size; + addr+= start_address; + } + return(addr); } -/* Set or clear bits, without callbacks */ void -cl_mem::set_bit1(t_addr addr, t_mem bits) +cl_memory::err_inv_addr(t_addr addr) { - if (addr >= size) + if (!uc) return; - bits&= mask; - if (width <= 8) - ((TYPE_UBYTE*)mem)[addr]|= bits; - else if (width <= 16) - ((TYPE_UWORD*)mem)[addr]|= bits; - else - ((TYPE_UDWORD*)mem)[addr]|= bits; + class cl_error *e= new cl_error_mem_invalid_address(this, addr); + uc->error(e); } void -cl_mem::set_bit0(t_addr addr, t_mem bits) +cl_memory::err_non_decoded(t_addr addr) { - if (addr >= size) + if (!uc) return; - bits&= mask; - if (width <= 8) - ((TYPE_UBYTE*)mem)[addr]&= ~bits; - else if (width <= 16) - ((TYPE_UWORD*)mem)[addr]&= ~bits; - else - ((TYPE_UDWORD*)mem)[addr]&= ~bits; + class cl_error *e= new cl_error_mem_non_decoded(this, addr); + uc->error(e); } -t_mem -cl_mem::add(t_addr addr, long what) -{ - if (addr >= size) - return(0); - if (width <= 8) - { - ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what; - return(((TYPE_UBYTE*)mem)[addr]); - } - else if (width <= 16) - { - ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what; - return(((TYPE_UWORD*)mem)[addr]); - } - else - { - ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what; - return(((TYPE_UDWORD*)mem)[addr]); - } -} t_addr -cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con) +cl_memory::dump(t_addr start, t_addr stop, int bpl, class cl_console *con) { int i; + t_addr lva= lowest_valid_address(); + t_addr hva= highest_valid_address(); + if (start < lva) + start= lva; + if (stop > hva) + stop= hva; while ((start <= stop) && - (start < size)) + (start < hva)) { con->dd_printf(addr_format, start); con->dd_printf(" "); for (i= 0; (i < bpl) && - (start+i < size) && + (start+i < hva) && (start+i <= stop); i++) { @@ -362,11 +195,11 @@ cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con) i++; } for (i= 0; (i < bpl) && - (start+i < size) && + (start+i < hva) && (start+i <= stop); i++) { - long c= get(start+i); + long c= read(start+i); con->dd_printf("%c", isprint(255&c)?(255&c):'.'); if (width > 8) con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.'); @@ -383,13 +216,14 @@ cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con) } t_addr -cl_mem::dump(class cl_console *con) +cl_memory::dump(class cl_console *con) { return(dump(dump_finished, dump_finished+10*8-1, 8, con)); } bool -cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr) +cl_memory::search_next(bool case_sensitive, + t_mem *array, int len, t_addr *addr) { t_addr a; int i; @@ -434,1056 +268,1169 @@ cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr) /* - * Bitmap + * Memory operators */ -/*cl_bitmap::cl_bitmap(t_addr asize): +cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell, + t_addr addr): cl_base() { - map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR)); - memset(map, 0, size); + cell= acell; + data= 0; + mask= ~0; + next_operator= 0; + address= addr; } -cl_bitmap::~cl_bitmap(void) +cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell, + t_addr addr, + t_mem *data_place, t_mem the_mask): + cl_base() { - free(map); + cell= acell; + data= data_place; + mask= the_mask; + next_operator= 0; + address= addr; } void -cl_bitmap::set(t_addr pos) +cl_memory_operator::set_data(t_mem *data_place, t_mem the_mask) { - int i; + data= data_place; + mask= the_mask; +} - if ((i= pos/(8*SIZEOF_CHAR)) < size) - map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1))); + +t_mem +cl_memory_operator::read(void) +{ + if (next_operator) + return(next_operator->read()); + else + return(*data); } -void -cl_bitmap::clear(t_addr pos) +t_mem +cl_memory_operator::write(t_mem val) { - int i; + if (next_operator) + return(next_operator->write(val)); + else + return(*data= (val & mask)); +} + - if ((i= pos/(8*SIZEOF_CHAR)) < size) - map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1))); +/* Memory operator for hw callbacks */ + +cl_hw_operator::cl_hw_operator(class cl_memory_cell *acell, t_addr addr, + t_mem *data_place, t_mem the_mask, + class cl_hw *ahw): + cl_memory_operator(acell, addr, data_place, the_mask) +{ + hw= ahw; } -bool -cl_bitmap::get(t_addr pos) + +t_mem +cl_hw_operator::read(void) +{ + t_mem d= 0; + + if (hw) + d= hw->read(cell); + + if (next_operator) + next_operator->read(); + + return(d); +} + +t_mem +cl_hw_operator::read(enum hw_cath skip) { - return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1)))); + t_mem d= *data; + + if (hw && + hw->cathegory != skip) + d= hw->read(cell); + + if (next_operator) + next_operator->read(); + + return(d); } -bool -cl_bitmap::empty(void) +t_mem +cl_hw_operator::write(t_mem val) { - int i; + if (hw) + hw->write(cell, &val); + if (next_operator) + val= next_operator->write(val); + return(*data= (val & mask)); +} - for (i= 0; i < size && map[i] == 0; i++) ; - return(i == size); -}*/ -/* - * Special memory for code (ROM) - */ +/* Write event break on cell */ + +cl_write_operator::cl_write_operator(class cl_memory_cell *acell, t_addr addr, + t_mem *data_place, t_mem the_mask, + class cl_uc *auc, class cl_brk *the_bp): + cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp) +{ + uc= auc; + bp= the_bp; +} -/*cl_rom::cl_rom(t_addr asize, int awidth, class cl_uc *auc): - cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth, auc) +t_mem +cl_write_operator::write(t_mem val) { - bp_map= new cl_bitmap(asize); - inst_map= new cl_bitmap(asize); + //printf("write event at 0x%x bp=%p\n",address,bp); + uc->events->add(bp); + if (next_operator) + return(next_operator->write(val)); + else + return(*data= (val & mask)); } -cl_rom::~cl_rom(void) + +/* Read event break on cell */ + +cl_read_operator::cl_read_operator(class cl_memory_cell *acell, t_addr addr, + t_mem *data_place, t_mem the_mask, + class cl_uc *auc, class cl_brk *the_bp): + cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp) { - delete bp_map; - delete inst_map; -}*/ + uc= auc; + bp= the_bp; +} + +t_mem +cl_read_operator::read(void) +{ + //printf("read event at 0x%x bp=%p\n",address,bp); + uc->events->add(bp); + if (next_operator) + return(next_operator->read()); + else + return(*data); +} /* - * New type of memory simulation + * Memory cell */ -cl_cell::cl_cell(void): +cl_memory_cell::cl_memory_cell(void): cl_base() { + data= (t_mem *)malloc(sizeof(t_mem)); + flags= CELL_NON_DECODED; + width= 8; + *data= 0; + #ifdef STATISTIC nuof_writes= nuof_reads= 0; #endif -} - -cl_normal_cell::cl_normal_cell(uchar awidth): - cl_cell() -{ - type= CELL_NORMAL; - data= 0; mask= 1; - width= awidth; - for (--awidth; awidth; awidth--) + int w= width; + for (--w; w; w--) { mask<<= 1; mask|= 1; } } -t_mem -cl_normal_cell::add(long what) +cl_memory_cell::~cl_memory_cell(void) { - t_mem d; - - if (width <= 8) - d= TYPE_BYTE(data) + what; - else if (width <= 16) - d= TYPE_WORD(data) + what; - else - d= TYPE_DWORD(data) + what; - return(data= d & mask); + if ((flags & CELL_NON_DECODED) && + data) + free(data); } -t_mem -cl_normal_cell::wadd(long what) +int +cl_memory_cell::init(void) { - t_mem d; - - if (width <= 8) - d= TYPE_BYTE(data) + what; - else if (width <= 16) - d= TYPE_WORD(data) + what; - else - d= TYPE_DWORD(data) + what; - return(write(d)); + cl_base::init(); + set(0/*rand()*/); + return(0); } -void -cl_normal_cell::set_bit1(t_mem bits) + +TYPE_UBYTE +cl_memory_cell::get_flags(void) { - bits&= mask; - data|= bits; + return(flags); +} + +bool +cl_memory_cell::get_flag(enum cell_flag flag) +{ + return(flags & flag); } void -cl_normal_cell::set_bit0(t_mem bits) +cl_memory_cell::set_flags(TYPE_UBYTE what) { - bits&= mask; - data&= ~bits; + flags= what; } +void +cl_memory_cell::set_flag(enum cell_flag flag, bool val) +{ + if (val) + flags|= flag; + else + flags&= ~(flag); +} -/* - */ -cl_registered_cell::cl_registered_cell(uchar awidth): - cl_normal_cell(awidth) +void +cl_memory_cell::un_decode(void) { - type= CELL_HW_READ | CELL_HW_WRITE; - //hws= new cl_list(1, 1); - hardwares= 0; - nuof_hws= 0; + if ((flags & CELL_NON_DECODED) == 0) + { + data= (t_mem *)malloc(sizeof(t_mem)); + flags|= CELL_NON_DECODED; + } } -cl_registered_cell::~cl_registered_cell(void) +void +cl_memory_cell::decode(class cl_memory_chip *chip, t_addr addr) { - if (hardwares) - free(hardwares); + if (flags & CELL_NON_DECODED) + free(data); + data= chip->get_slot(addr); + if (!data) + { + data= (t_mem *)malloc(sizeof(t_mem)); + flags|= CELL_NON_DECODED; + } + else + flags&= ~(CELL_NON_DECODED); } -/*void -cl_registered_cell::destroy(void) -{ - hardwares= 0; - nuof_hws= 0; -}*/ t_mem -cl_registered_cell::read(void) +cl_memory_cell::read(void) { - int i; - t_mem d= data; - - if (nuof_hws) - for (i= 0; i < nuof_hws; i++) - { - d= hardwares[i]->read(this); - ; - } #ifdef STATISTIC nuof_reads++; #endif - return(d & mask); + if (operators) + return(operators->read()); + return(*data); } t_mem -cl_registered_cell::read(enum hw_cath skip) +cl_memory_cell::read(enum hw_cath skip) { - int i; - t_mem d= data; - - if (nuof_hws) - for (i= 0; i < nuof_hws; i++) - { - if ((skip & hardwares[i]->cathegory) == 0) - d= hardwares[i]->read(this); - ; - } #ifdef STATISTIC nuof_reads++; #endif - return(d & mask); + if (operators) + return(operators->read(skip)); + return(*data); } - + t_mem -cl_registered_cell::write(t_mem val) +cl_memory_cell::get(void) { - int i; + return(*data); +} - val&= mask; - if (nuof_hws) - for (i= 0; i < nuof_hws; i++) - { - hardwares[i]->write(this, &val); - ; - } +t_mem +cl_memory_cell::write(t_mem val) +{ #ifdef STATISTIC nuof_writes++; #endif - return(data= val & mask); -} - -class cl_cell * -cl_registered_cell::add_hw(class cl_hw *hw, int *ith) -{ - if (!hw) - { - /* Whatta hell!? */ - return(0); - } - if (!hardwares) - hardwares= (class cl_hw **)malloc(sizeof(class cl_hw *)); - else - hardwares= (class cl_hw **)realloc(hardwares, - sizeof(class c_hw *) * (nuof_hws+1)); - hardwares[nuof_hws]= hw; - nuof_hws++; - if (ith) - *ith= nuof_hws-1; - return(this); + if (operators) + return(operators->write(val)); + *data= val & mask; + return(*data); } -class cl_hw * -cl_registered_cell::get_hw(int ith) +t_mem +cl_memory_cell::set(t_mem val) { - if (ith >= nuof_hws) - return(0); - return(hardwares[ith]); + *data= val & mask; + return(*data); } -/* - */ -cl_event_handler::cl_event_handler(class cl_uc *auc): - cl_base() +t_mem +cl_memory_cell::add(long what) { - uc= auc; - read_bps= new cl_list(1, 1); - write_bps= new cl_list(1, 1); + *data= (*data + what) & mask; + return(*data); } -cl_event_handler::~cl_event_handler(void) +t_mem +cl_memory_cell::wadd(long what) { - read_bps->disconn_all(); - write_bps->disconn_all(); - delete read_bps; - delete write_bps; + t_mem d= (*data + what) & mask; + return(write(d)); } void -cl_event_handler::write(void) +cl_memory_cell::set_bit1(t_mem bits) { - int i; - - for (i= 0; i < write_bps->count; i++) - { - class cl_brk *bp= (class cl_brk *)(write_bps->at(i)); - uc->events->add(bp); - } + bits&= mask; + (*data)|= bits; } void -cl_event_handler::read(void) +cl_memory_cell::set_bit0(t_mem bits) { - int i; + bits&= mask; + (*data)&= ~bits; +} + - for (i= 0; i < read_bps->count; i++) +void +cl_memory_cell::append_operator(class cl_memory_operator *op) +{ + if (!operators) + operators= op; + else { - class cl_brk *bp= (class cl_brk *)(read_bps->at(i)); - uc->events->add(bp); + class cl_memory_operator *o= operators, *n; + n= o->get_next(); + while (n) + { + o= n; + n= o->get_next(); + } + o->set_next(op); } } -int -cl_event_handler::add_bp(class cl_brk *bp) +void +cl_memory_cell::prepend_operator(class cl_memory_operator *op) { - int t= CELL_NORMAL; - - if (!bp) - return(CELL_NORMAL); - switch (bp->get_event()) + if (op) { - case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: - t|= CELL_WRITE_BRK; - write_bps->add(bp); - break; - case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR: - t|= CELL_READ_BRK; - read_bps->add(bp); - break; - default: - t|= CELL_READ_BRK | CELL_WRITE_BRK; - read_bps->add(bp); - write_bps->add(bp); - break; + op->set_next(operators); + operators= op; } - return(t); } -int -cl_event_handler::copy_from(class cl_event_handler *eh) +void +cl_memory_cell::del_operator(class cl_brk *brk) { - int i, t= CELL_NORMAL; - - if (!eh) - return(t); - for (i= 0; i < eh->read_bps->count; i++) + if (!operators) + return; + class cl_memory_operator *op= operators; + if (operators->match(brk)) { - class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i)); - t|= add_bp(bp); + operators= op->get_next(); + delete op; } - for (i= 0; i < eh->write_bps->count; i++) + else { - class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i)); - t|= add_bp(bp); + while (op->get_next() && + !op->get_next()->match(brk)) + op= op->get_next(); + if (op->get_next()) + { + class cl_memory_operator *m= op->get_next(); + op->set_next(m->get_next());; + delete m; + } } - return(t); } -int -cl_event_handler::del_bp(class cl_brk *bp) -{ - int t= CELL_NORMAL; - write_bps->disconn(bp); - read_bps->disconn(bp); - if (write_bps->count) - t|= CELL_WRITE_BRK; - if (read_bps->count) - t|= CELL_READ_BRK; - return(t); +class cl_memory_cell * +cl_memory_cell::add_hw(class cl_hw *hw, int *ith, t_addr addr) +{ + class cl_hw_operator *o= new cl_hw_operator(this, addr, data, mask, hw); + append_operator(o); + return(this); } +/*class cl_hw * +cl_memory_cell::get_hw(int ith) +{ + return(0); +}*/ -/* - */ - -cl_event_cell::cl_event_cell(uchar awidth, class cl_uc *auc): - cl_normal_cell(awidth) -{ - eh= new cl_event_handler(auc); -} - -cl_event_cell::~cl_event_cell(void) -{ - delete eh; -} - -t_mem -cl_event_cell::read(void) -{ - if (type & CELL_READ_BRK) - eh->read(); - return(cl_normal_cell::read()); -} - -t_mem -cl_event_cell::write(t_mem val) +class cl_event_handler * +cl_memory_cell::get_event_handler(void) { - if (type & CELL_WRITE_BRK) - eh->write(); - return(cl_normal_cell::write(val)); + return(0); } /* + * Dummy cell for non-existent addresses */ -cl_ev_reg_cell::cl_ev_reg_cell(uchar awidth, class cl_uc *auc): - cl_registered_cell(awidth) -{ - eh= new cl_event_handler(auc); -} - -cl_ev_reg_cell::~cl_ev_reg_cell(void) -{} - t_mem -cl_ev_reg_cell::read(void) +cl_dummy_cell::write(t_mem val) { - if (type & CELL_READ_BRK) - eh->read(); - return(cl_registered_cell::read()); +#ifdef STATISTIC + nuof_writes++; +#endif + *data= rand() & mask; + return(*data); } t_mem -cl_ev_reg_cell::write(t_mem val) +cl_dummy_cell::set(t_mem val) { - if (type & CELL_WRITE_BRK) - eh->write(); - return(cl_registered_cell::write(val)); + *data= rand() & mask; + return(*data); } /* + * Address space */ -cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell) +cl_address_space::cl_address_space(char *id, + t_addr astart, t_addr asize, int awidth): + cl_memory(id, asize, awidth) { - real_cell= realcell; + start_address= astart; + decoders= new cl_decoder_list(2, 2, DD_FALSE); + cells= (class cl_memory_cell **)malloc(size * sizeof(class cl_memory_cell*)); + int i; + for (i= 0; i < size; i++) + { + cells[i]= new cl_memory_cell(); + cells[i]->init(); + } + dummy= new cl_dummy_cell(); } -cl_mapped_cell::~cl_mapped_cell(void) -{} - -t_mem -cl_mapped_cell::read(void) +cl_address_space::~cl_address_space(void) { - return(real_cell->read()); + delete decoders; + int i; + for (i= 0; i < size; i++) + if (cells[i]) + delete cells[i]; + delete dummy; } + t_mem -cl_mapped_cell::read(enum hw_cath skip) +cl_address_space::read(t_addr addr) { - return(real_cell->read(skip)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + return(dummy->read()); + } + return(cells[idx]->read()); } t_mem -cl_mapped_cell::get(void) +cl_address_space::read(t_addr addr, enum hw_cath skip) { - return(real_cell->get()); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + return(dummy->read()); + } + return(cells[idx]->read(skip)); } t_mem -cl_mapped_cell::write(t_mem val) +cl_address_space::get(t_addr addr) { - return(real_cell->write(val)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + return(dummy->get()); + } + return(cells[idx]->get()); } t_mem -cl_mapped_cell::set(t_mem val) +cl_address_space::write(t_addr addr, t_mem val) { - return(real_cell->set(val)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + return(dummy->write(val)); + } + return(cells[idx]->write(val)); } -t_mem -cl_mapped_cell::add(long what) +void +cl_address_space::set(t_addr addr, t_mem val) { - return(real_cell->add(what)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + dummy->set(val); + return; + } + cells[idx]->set(val); } t_mem -cl_mapped_cell::wadd(long what) +cl_address_space::wadd(t_addr addr, long what) { - return(real_cell->wadd(what)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + { + err_inv_addr(addr); + } + return(cells[idx]->wadd(what)); } -void -cl_mapped_cell::set_bit1(t_mem bits) -{ - return(real_cell->set_bit1(bits)); -} +/* Set or clear bits, without callbacks */ void -cl_mapped_cell::set_bit0(t_mem bits) -{ - return(real_cell->set_bit0(bits)); -} - -class cl_cell * -cl_mapped_cell::add_hw(class cl_hw *hw, int *ith) -{ - return(real_cell->add_hw(hw, ith)); -} - -class cl_hw * -cl_mapped_cell::get_hw(int ith) +cl_address_space::set_bit1(t_addr addr, t_mem bits) { - return(real_cell->get_hw(ith)); -} - -class cl_event_handler * -cl_mapped_cell::get_event_handler(void) -{ - return(real_cell->get_event_handler()); -} - - -/* - */ - -cl_m::cl_m(enum mem_class atype, char *aclass_name, t_addr asize, int awidth, - class cl_uc *auc): - cl_mem(atype, aclass_name, 0, awidth, auc) -{ - t_addr a; - - size= asize; - width= awidth; - array= (class cl_cell **)calloc(size, sizeof(class cl_cell *)); - for (a= 0; a < size; a++) - array[a]= new cl_normal_cell(width); - bus_mask= 0; - t_addr i; - for (i= 1; i < size; i<<=1) - bus_mask= (bus_mask<<1)|1; - dummy= new cl_normal_cell(width); - //mk_cell(size, 0); -} - -cl_m::~cl_m(void) -{ - t_addr a; - - for (a= 0; a < size; a++) - delete array[a]; - free(array); - delete dummy; + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return; + class cl_memory_cell *cell= cells[idx]; + cell->set_bit1(bits); } void -cl_m::err_inv_addr(t_addr addr) +cl_address_space::set_bit0(t_addr addr, t_mem bits) { - if (!uc) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) return; - class cl_error *e= new cl_err_inv_addr(this, addr); - uc->error(e); + class cl_memory_cell *cell= cells[idx]; + cell->set_bit0(bits); } -/*void -cl_m::mk_cell(t_addr addr, class cl_cell *cell) + +class cl_memory_cell * +cl_address_space::get_cell(t_addr addr) { - if (!cell) - cell= new cl_cell(width); - class cl_cell *p; - if (addr >= size) - p= dummy; - else - p= array[addr]; - if (p == 0) - { - p= (class cl_cell *)calloc(1, sizeof(*cell)); - } - else + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) { - p->destroy(); - p= (class cl_cell *)realloc(p, sizeof(cell)); + err_inv_addr(addr); + return(dummy); } - memcpy(p, cell, sizeof(*cell)); - cell->destroy(); - delete cell; -}*/ + return(cells[idx]); +} + int -cl_m::get_cell_flag(t_addr addr) +cl_address_space::get_cell_flag(t_addr addr) { - if (addr >= size) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) { - return(dummy->get_type()); + return(dummy->get_flags()); } - return(array[addr]->get_type()); + return(cells[addr]->get_flags()); } bool -cl_m::get_cell_flag(t_addr addr, int flag) +cl_address_space::get_cell_flag(t_addr addr, enum cell_flag flag) { - if (addr >= size) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) { - return(dummy->get_type() & flag); + return(dummy->get_flag(flag)); } - return(array[addr]->get_type() & flag); + return(cells[addr]->get_flag(flag)); } void -cl_m::set_cell_flag(t_addr addr, bool set_to, int flag) +cl_address_space::set_cell_flag(t_addr addr, bool set_to, enum cell_flag flag) { - class cl_cell *cell; + t_addr idx= addr-start_address; + class cl_memory_cell *cell; - if (addr >= size) + if (idx >= size || + addr < start_address) { cell= dummy; } else - cell= array[addr]; - if (set_to) - cell->set_type(cell->get_type() | flag); - else - cell->set_type(cell->get_type() & ~flag); + cell= cells[addr]; + cell->set_flag(flag, set_to); } -t_mem -cl_m::read(t_addr addr) + +bool +cl_address_space::decode_cell(t_addr addr, + class cl_memory_chip *chip, t_addr chipaddr) { - //addr&= bus_mask; - if (addr >= size) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return(DD_FALSE); + class cl_memory_cell *cell= cells[idx]; + + if (!cell->get_flag(CELL_NON_DECODED)) { - err_inv_addr(addr); - return(dummy->read()); + // un-decode first! + cell->un_decode(); } - return(array[addr]->read()); + cell->decode(chip, chipaddr); + + return(!cell->get_flag(CELL_NON_DECODED)); } -t_mem -cl_m::read(t_addr addr, enum hw_cath skip) +void +cl_address_space::undecode_cell(t_addr addr) { - //addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - return(dummy->read(skip)); - } - return(array[addr]->read(skip)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return; + class cl_memory_cell *cell= cells[idx]; + + cell->un_decode(); } -t_mem -cl_m::get(t_addr addr) +void +cl_address_space::undecode_area(class cl_address_decoder *skip, + t_addr begin, t_addr end,class cl_console *con) { - addr&= bus_mask; - if (addr >= size) +#define D if (con) con->debug + D("Undecoding area 0x%x-0x%x of %s\n", begin, end, get_name()); + int i; + for (i= 0; i < decoders->count; i++) { - err_inv_addr(addr); - return(dummy->get()); + class cl_address_decoder *d= + dynamic_cast(decoders->object_at(i)); + if (!d || + d == skip) + continue; + D(" Checking decoder 0x%x-0x%x -> %s[0x%x]\n", + d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin); + if (d->fully_covered_by(begin, end)) + { + // decoder can be removed + D(" Can be removed\n"); + decoders->disconn(d); + i--; + delete d; + if (decoders->count == 0) + break; + } + else if (d->covers(begin, end)) + { + // decoder must be split + D(" Must be split\n"); + class cl_address_decoder *nd= d->split(begin, end); + D(" After split:\n"); + D(" 0x%x-0x%x -> %s[0x%x]\n", + d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin); + if (nd) + { + decoders->add(nd); + D(" 0x%x-0x%x -> %s[0x%x]\n", + nd->as_begin, nd->as_end, nd->memchip->get_name(), nd->chip_begin); + nd->activate(con); + } + } + else if (d->is_in(begin, end)) + { + // decoder sould shrink + D(" Sould shrink\n"); + if (d->shrink_out_of(begin, end)) + { + D(" Can be removed after shrink\n"); + decoders->disconn(d); + i--; + delete d; + if (decoders->count == 0) + break; + } + else + { + D(" Shrinked to 0x%x-0x%x -> %s[0x%x]\n", + d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin); + } + } } - return(array[addr]->get()); +#undef D } -t_mem -cl_m::write(t_addr addr, t_mem val) + +class cl_memory_cell * +cl_address_space::register_hw(t_addr addr, class cl_hw *hw, + int *ith, + bool announce) { - //addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - return(dummy->write(val)); - } - return(array[addr]->write(val)); + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return(0); + class cl_memory_cell *cell= cells[idx]; + cell->add_hw(hw, ith, addr); + //printf("adding hw %s to cell 0x%x(%d) of %s\n", hw->id_string, addr, idx, get_name("as")); + if (announce) + ;//uc->sim->/*app->*/mem_cell_changed(this, addr);//FIXME + return(cell); } + void -cl_m::set(t_addr addr, t_mem val) +cl_address_space::set_brk(t_addr addr, class cl_brk *brk) { - if (addr >= size) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return; + class cl_memory_cell *cell= cells[idx]; + class cl_memory_operator *op; + + switch (brk->get_event()) { - err_inv_addr(addr); - //addr&= bus_mask; - dummy->set(val); + case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: + //e= 'W'; + op= new cl_write_operator(cell, addr, cell->get_data(), cell->get_mask(), + uc, brk); + break; + case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR: + //e= 'R'; + op= new cl_read_operator(cell, addr, cell->get_data(), cell->get_mask(), + uc, brk); + break; + case brkNONE: + set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK); return; + break; + default: + //e= '.'; + op= 0; + break; } - //addr&= bus_mask; - array[addr]->set(val); + if (op) + cell->append_operator(op); } -class cl_cell * -cl_m::get_cell(t_addr addr) +void +cl_address_space::del_brk(t_addr addr, class cl_brk *brk) { - //addr&= bus_mask; - if (addr >= size) + t_addr idx= addr-start_address; + if (idx >= size || + addr < start_address) + return; + class cl_memory_cell *cell= cells[idx]; + + switch (brk->get_event()) { - err_inv_addr(addr); - return(dummy); + case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: + case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR: + cell->del_operator(brk); + break; + case brkNONE: + set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK); + return; + break; + default: + break; } - return(array[addr]); } -/* Set or clear bits, without callbacks */ +/* + * List of address spaces + */ -void -cl_m::set_bit1(t_addr addr, t_mem bits) +cl_address_space_list::cl_address_space_list(class cl_uc *the_uc): + cl_list(2, 2, "address spaces") { - class cl_cell *cell; - - addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - cell= dummy; - } - else - cell= array[addr]; - bits&= cell->get_mask(); - cell->set(cell->get() | bits); + uc= the_uc; } -void -cl_m::write_bit1(t_addr addr, t_mem bits) +t_index +cl_address_space_list::add(class cl_address_space *mem) { - class cl_cell *cell; - - addr&= bus_mask; - if (addr >= size) + mem->set_uc(uc); + t_index ret= cl_list::add(mem); + if (uc) { - err_inv_addr(addr); - cell= dummy; + class cl_event_address_space_added e(mem); + uc->handle_event(e); } - else - cell= array[addr]; - bits&= cell->get_mask(); - cell->write(cell->get() | bits); + return(ret); } -void -cl_m::set_bit0(t_addr addr, t_mem bits) + +/* + * Memory chip + */ + +cl_memory_chip::cl_memory_chip(char *id, int asize, int awidth, int initial): + cl_memory(id, asize, awidth) { - class cl_cell *cell; + array= (t_mem *)malloc(size * sizeof(t_mem)); + init_value= initial; +} - addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - cell= dummy; - } - else - cell= array[addr]; - bits&= cell->get_mask(); - cell->set(cell->get() & ~bits); +cl_memory_chip::~cl_memory_chip(void) +{ + if (array) + free(array); } -void -cl_m::write_bit0(t_addr addr, t_mem bits) +int +cl_memory_chip::init(void) { - class cl_cell *cell; + cl_memory::init(); + int i; + for (i= 0; i < size; i++) + set(i, + (init_value<0)?rand():(init_value)); + return(0); +} - addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - cell =dummy; - } - else - cell= array[addr]; - bits&= cell->get_mask(); - cell->write(cell->get() & ~bits); + +t_mem * +cl_memory_chip::get_slot(t_addr addr) +{ + if (!array || + size <= addr) + return(0); + return(&array[addr]); } + t_mem -cl_m::add(t_addr addr, long what) +cl_memory_chip::get(t_addr addr) { - addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - return(dummy->add(what)); - } - return(array[addr]->add(what)); + if (!array || + size <= addr) + return(0); + return(array[addr]); } -t_mem -cl_m::wadd(t_addr addr, long what) +void +cl_memory_chip::set(t_addr addr, t_mem val) { - addr&= bus_mask; - if (addr >= size) - { - err_inv_addr(addr); - return(dummy->wadd(what)); - } - return(array[addr]->wadd(what)); + if (!array || + size <= addr) + return; + array[addr]= val & data_mask; } -class cl_cell * -cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce) +void +cl_memory_chip::set_bit1(t_addr addr, t_mem bits) { - class cl_cell *cell, *nc; + if (!array || + size <= addr) + return; + array[addr]|= (bits & data_mask); +} - addr&= bus_mask; - if (addr >= size) - cell= dummy; - else - cell= array[addr]; +void +cl_memory_chip::set_bit0(t_addr addr, t_mem bits) +{ + if (!array || + size <= addr) + return; + array[addr]&= ((~bits) & data_mask); +} - if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE)) - { - /* Already registered */ - return(cell->add_hw(hw, ith)); - } - else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK)) - { - /* Event break is set on it, now register hw */ - nc= new cl_ev_reg_cell(width, uc); - nc->set(cell->get()); - nc->set_type(nc->get_type() & - ~(CELL_GENERAL|CELL_READ_BRK|CELL_WRITE_BRK)); - nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL)); - class cl_event_handler *eh= nc->get_event_handler(); - if (eh) - nc->set_type(nc->get_type() | eh->copy_from(cell->get_event_handler())); - nc->add_hw(hw, ith); - } - else - { - /* Normal cell, register hw */ - nc= new cl_registered_cell(width); - nc->set(cell->get()); - nc->set_type(nc->get_type() & ~CELL_GENERAL); - nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL)); - nc->add_hw(hw, ith); - } - if (addr >= size) - { - delete dummy; - dummy= nc; - } +/* + * Address decoder + */ + +cl_address_decoder::cl_address_decoder(class cl_memory *as, + class cl_memory *chip, + t_addr asb, t_addr ase, t_addr cb) +{ + if (as->is_address_space()) + address_space= (class cl_address_space *)as; else - { - delete array[addr]; - array[addr]= nc; - } - if (announce) - uc->sim->/*app->*/mem_cell_changed(this, addr); - return(nc); + address_space= 0; + if (chip->is_chip()) + memchip= (class cl_memory_chip *)chip; + else + memchip= 0; + as_begin= asb; + as_end= ase; + chip_begin= cb; + activated= DD_FALSE; } -void -cl_m::set_brk(t_addr addr, class cl_brk *brk) +cl_address_decoder::~cl_address_decoder(void) { - class cl_cell *cell, *nc; - char e= '_'; + t_addr a; + if (address_space) + for (a= as_begin; a <= as_end; a++) + address_space->undecode_cell(a); +} - addr&= bus_mask; - if (addr >= size) - cell= dummy; - else - cell= array[addr]; +int +cl_address_decoder::init(void) +{ + return(0); +} - switch (brk->get_event()) + +bool +cl_address_decoder::activate(class cl_console *con) +{ +#define D if (con) con->debug + D("Activation of an address decoder\n"); + if (activated) { - case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: - e= 'W'; - break; - case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR: - e= 'R'; - break; - case brkNONE: - set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK); - return; - break; - default: e= '.'; break; + D("Already activated\n"); + return(DD_FALSE); } - - if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE)) + if (!address_space || + !address_space->is_address_space()) { - /* Hw is registered on it, now set event break */ - nc= new cl_ev_reg_cell(width, uc); - nc->set(cell->get()); - nc->set_type(nc->get_type() & ~CELL_GENERAL); - nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL)); - int i= 0; - class cl_hw *hw; - while ((hw= cell->get_hw(i)) != 0) - { - nc->add_hw(hw, 0); - i++; - } - if (((class cl_registered_cell *)cell)->hardwares) - { - free(((class cl_registered_cell *)cell)->hardwares); - ((class cl_registered_cell *)cell)->hardwares= 0; - } - class cl_event_handler *eh; - if ((eh= nc->get_event_handler())) - nc->set_type(nc->get_type() | eh->add_bp(brk)); + D("No or non address space\n"); + return(DD_FALSE); } - else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK)) + if (!memchip || + !memchip->is_chip()) { - /* Break is already set on it */ - class cl_event_handler *eh; - if ((eh= cell->get_event_handler())) - cell->set_type(cell->get_type() | eh->add_bp(brk)); - return; + D("No or non memory chip\n"); + return(DD_FALSE); } - else + if (as_begin > as_end) { - /* Normal cell, set event break */ - nc= new cl_event_cell(width, uc); - nc->set(cell->get()); - nc->set_type(nc->get_type() & ~CELL_GENERAL); - nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL)); - class cl_event_handler *eh; - if ((eh= nc->get_event_handler())) - nc->set_type(nc->get_type() | eh->add_bp(brk)); + D("Wrong address area specification\n"); + return(DD_FALSE); } - - if (addr >= size) + if (chip_begin >= memchip->get_size()) { - delete dummy; - dummy= nc; + D("Wrong chip area specification\n"); + return(DD_FALSE); } - else + if (as_begin < address_space->start_address || + as_end >= address_space->start_address + address_space->get_size()) { - delete array[addr]; - array[addr]= nc; + D("Specified area is out of address space\n"); + return(DD_FALSE); } - uc->sim->/*app->*/mem_cell_changed(this, addr); -} - -void -cl_m::del_brk(t_addr addr, class cl_brk *brk) -{ - class cl_cell *cell, *nc; - char e= '_'; - - addr&= bus_mask; - if (addr >= size) - cell= dummy; - else - cell= array[addr]; - - switch (brk->get_event()) + if (as_end-as_begin > memchip->get_size()-chip_begin) { - case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: e= 'W'; break; - case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR: - e= 'R'; - break; - case brkNONE: - set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK); - return; - break; - default: e= '.'; break; + D("Specified area is out of chip size\n"); + return(DD_FALSE); } - - if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE)) + + address_space->undecode_area(this, as_begin, as_end, con); + + t_addr asa, ca; + for (asa= as_begin, ca= chip_begin; + asa <= as_end; + asa++, ca++) { - /* Hw is registered on it, delete event break */ - class cl_event_handler *eh; - int t= CELL_NORMAL; - if ((eh= cell->get_event_handler())) - t= eh->del_bp(brk); - if (t & (CELL_READ_BRK|CELL_WRITE_BRK)) + if (!address_space->decode_cell(asa, memchip, ca)) { - cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK)); - cell->set_type(cell->get_type() | t); - return; + D("Decoding 0x%06x->0x%06x failed\n", asa, ca); } - nc= new cl_registered_cell(width); - nc->set(cell->get()); - nc->set_type(cell->get_type() & ~CELL_GENERAL); - nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL)); - int i= 0; - class cl_hw *hw; - while ((hw= cell->get_hw(i)) != 0) - { - nc->add_hw(hw, 0); - i++; - } - if (((class cl_registered_cell *)cell)->hardwares) - free(((class cl_registered_cell *)cell)->hardwares); } - else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK)) + activated= DD_TRUE; + +#undef D + return(activated); +} + + +bool +cl_address_decoder::fully_covered_by(t_addr begin, t_addr end) +{ + if (begin <= as_begin && + end >= as_end) + return(DD_TRUE); + return(DD_FALSE); +} + +bool +cl_address_decoder::is_in(t_addr begin, t_addr end) +{ + if (begin >= as_begin && + begin <= as_end) + return(DD_TRUE); + if (end >= as_begin && + end <= as_end) + return(DD_TRUE); + return(DD_FALSE); +} + +bool +cl_address_decoder::covers(t_addr begin, t_addr end) +{ + if (begin > as_begin && + end < as_end) + return(DD_TRUE); + return(DD_FALSE); +} + + +/* Returns TRUE if shrunken decoder is unnecessary */ + +bool +cl_address_decoder::shrink_out_of(t_addr begin, t_addr end) +{ + t_addr a= as_begin; + + if (!address_space) + return(DD_TRUE); + if (begin > a) + a= begin; + while (a <= end && + a <= as_end) { - /* Break already set on it, delete brk */ - class cl_event_handler *eh; - int t= CELL_NORMAL; - if ((eh= cell->get_event_handler())) - t= eh->del_bp(brk); - if (t & (CELL_READ_BRK|CELL_WRITE_BRK)) - { - cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK)); - cell->set_type(cell->get_type() | t); - return; - } - nc= new cl_normal_cell(width); - nc->set(cell->get()); - nc->set_type(cell->get_type() & ~CELL_GENERAL); - nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL)); - return; + address_space->undecode_cell(a); + a++; } - else + if (begin > as_begin) + as_end= begin-1; + if (as_end > end) { - /* Normal cell */ - return; + chip_begin+= (end-as_begin+1); + as_begin= end+1; } + if (as_end < as_begin) + return(DD_TRUE); + return(DD_FALSE); +} - if (addr >= size) +class cl_address_decoder * +cl_address_decoder::split(t_addr begin, t_addr end) +{ + class cl_address_decoder *nd= 0; + if (begin > as_begin) { - delete dummy; - dummy= nc; + if (as_end > end) + nd= new cl_address_decoder(address_space, memchip, + end+1, as_end, chip_begin+(end-as_begin)+1); + shrink_out_of(begin, as_end); } - else + else if (end < as_end) { - delete array[addr]; - array[addr]= nc; + if (as_begin < begin) + nd= new cl_address_decoder(address_space, memchip, + as_begin, begin-1, chip_begin); + shrink_out_of(end+1, as_end); } - uc->sim->/*app->*/mem_cell_changed(this, addr); + if (nd) + nd->init(); + return(nd); } -#ifdef STATISTIC -unsigned long -cl_m::get_nuof_reads(void) -{ - unsigned long res= 0; - t_addr i; - for (i= 0; i < size; i++) - res+= array[i]->nuof_reads; - return(res); -} +/* + * List of address decoders + */ -unsigned long -cl_m::get_nuof_writes(void) +cl_decoder_list::cl_decoder_list(t_index alimit, t_index adelta, bool bychip): + cl_sorted_list(alimit, adelta, "decoder list") { - unsigned long res= 0; - t_addr i; - for (i= 0; i < size; i++) - res+= array[i]->nuof_writes; - return(res); + Duplicates= DD_TRUE; + by_chip= bychip; } -void -cl_m::set_nuof_reads(unsigned long value) +void * +cl_decoder_list::key_of(void *item) { - t_addr i; - for (i= 0; i < size; i++) - array[i]->nuof_reads= value; - dummy->nuof_reads= value; + class cl_address_decoder *d= (class cl_address_decoder *)item; + if (by_chip) + return(&(d->chip_begin)); + else + return(&(d->as_begin)); } -void -cl_m::set_nuof_writes(unsigned long value) +int +cl_decoder_list::compare(void *key1, void *key2) { - t_addr i; - for (i= 0; i < size; i++) - array[i]->nuof_writes= value; - dummy->nuof_writes= value; + t_addr k1= *((t_addr*)key1), k2= *((t_addr*)key2); + if (k1 == k2) + return(0); + else if (k1 > k2) + return(1); + return(-1); } -#endif /* * Errors in memory handling */ -cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr): - cl_error() +/* All of memory errors */ +ERROR_CLASS_DEF_PARENT_ON(err_error, mem, "memory", + error_class_base, ERROR_ON); + +cl_error_mem::cl_error_mem(class cl_memory *amem, t_addr aaddr) { mem= amem; addr= aaddr; + classification= &error_mem_class; +} + +/* Invalid address in memory access */ +ERROR_CLASS_DEF_PARENT(err_error, + mem_invalid_address, + "invalid_address", + error_mem_class); + +cl_error_mem_invalid_address:: +cl_error_mem_invalid_address(class cl_memory *amem, t_addr aaddr): + cl_error_mem(amem, aaddr) +{ + classification= &error_mem_invalid_address_class; +} + +void +cl_error_mem_invalid_address::print(class cl_commander *c) +{ + c->dd_printf(get_type_name()); + c->dd_printf(": invalid address ", get_type_name()); + c->dd_printf(mem->addr_format, addr); + c->dd_printf(" in memory "); + c->dd_printf(mem->get_name()); + c->dd_printf(".\n"); +} + +/* Non-decoded address space access */ +ERROR_CLASS_DEF_PARENT(err_error, + mem_non_decoded, + "non_decoded", + error_mem_class); + +cl_error_mem_non_decoded:: +cl_error_mem_non_decoded(class cl_memory *amem, t_addr aaddr): + cl_error_mem(amem, aaddr) +{ + classification= &error_mem_non_decoded_class; } void -cl_err_inv_addr::print(class cl_commander *c) +cl_error_mem_non_decoded::print(class cl_commander *c) { - c->dd_printf("Error: invalid address "); + c->dd_printf(get_type_name()); + c->dd_printf(": access of non-decoded address "); c->dd_printf(mem->addr_format, addr); - c->dd_printf(" in memory %s.\n", mem->class_name); + c->dd_printf(" in memory "); + c->dd_printf(mem->get_name()); + c->dd_printf(".\n"); }