#include "utils.h"
#include "globals.h"
+// sim
+#include "simcl.h"
+
// cmd
#include "newcmdcl.h"
* Memory location handled specially by a hw element
*/
-cl_memloc::cl_memloc(t_addr addr):
+/*cl_memloc::cl_memloc(t_addr addr):
cl_base()
{
address= addr;
hws= new cl_list(2, 2);
hws->init();
-}
+}*/
-cl_memloc::~cl_memloc(void)
+/*cl_memloc::~cl_memloc(void)
{
hws->disconn_all();
delete hws;
-}
+}*/
-ulong
+/*ulong
cl_memloc::read(class cl_mem *mem)
{
uchar ret= 0;
if ((hw= (class cl_hw *)(hws->at(0))))
ret= hw->read(mem, address);
return(ret);
-}
+}*/
-void
+/*void
cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
{
class cl_hw *hw;
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_memloc_coll::cl_memloc_coll(void):
cl_sorted_list(2, 2)
{
Duplicates= DD_FALSE;
-}
+}*/
-void *
+/*void *
cl_memloc_coll::key_of(void *item)
{
return(&(((class cl_memloc *)item)->address));
-}
+}*/
-int
+/*int
cl_memloc_coll::compare(void *key1, void *key2)
{
if (*(long*)key1 > *(long*)key2)
return(-1);
else
return(0);
-}
+}*/
-class cl_memloc *
+/*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);
-}
+}*/
/*
*/
cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
- t_addr asize, int awidth):
+ t_addr asize, int awidth, class cl_uc *auc):
cl_guiobj()
{
int i;
-
+
+ uc= auc;
type= atype;
class_name= aclass_name;
width= awidth;
mem= 0;
for (i= width, mask= 0; i; i--)
mask= (mask<<1) | 1;
- if (width <= 8)
+ 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();
+ //read_locs= new cl_memloc_coll();
+ //write_locs= new cl_memloc_coll();
dump_finished= 0;
- addr_format= (char *)malloc(10);
- sprintf(addr_format, "0x%%0%dx",
- size-1<=0xf?1:
- (size-1<=0xff?2:
- (size-1<=0xfff?3:
- (size-1<=0xffff?4:
- (size-1<=0xfffff?5:
- (size-1<=0xffffff?6:12))))));
- data_format= (char *)malloc(10);
- sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
+ addr_format= data_format= 0;
}
cl_mem::~cl_mem(void)
free(addr_format);
if (data_format)
free(data_format);
- delete read_locs;
- delete write_locs;
+ //delete read_locs;
+ //delete write_locs;
}
int
{
t_addr i;
+ addr_format= (char *)malloc(10);
+ sprintf(addr_format, "0x%%0%dx",
+ size-1<=0xf?1:
+ (size-1<=0xff?2:
+ (size-1<=0xfff?3:
+ (size-1<=0xffff?4:
+ (size-1<=0xfffff?5:
+ (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);
return(0);
t_mem
cl_mem::read(t_addr addr)
{
- class cl_memloc *loc;
+ //class cl_memloc *loc;
if (addr >= size)
{
//FIXME
- fprintf(stderr, "Address 0x%06lx is over 0x%06lx\n", addr, size);
+ 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 ((loc= read_locs->get_loc(addr)))
+ return(loc->read(this));*/
if (width <= 8)
return((((TYPE_UBYTE*)mem)[addr])&mask);
else if (width <= 16)
/* Write calls callbacks of HW elements */
-void
-cl_mem::write(t_addr addr, t_mem *val)
+t_mem
+cl_mem::write(t_addr addr, t_mem val)
{
- class cl_memloc *loc;
+ /* class cl_memloc *loc;
if (addr >= size)
return;
else if (width <= 16)
((TYPE_UWORD*)mem)[addr]= (*val)&mask;
else
- ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;
+ ((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);
}
/* Set doesn't call callbacks */
while ((start <= stop) &&
(start < size))
{
- con->printf(addr_format, start); con->printf(" ");
+ con->dd_printf(addr_format, start); con->dd_printf(" ");
for (i= 0;
(i < bpl) &&
(start+i < size) &&
(start+i <= stop);
i++)
{
- con->printf(data_format, read(start+i)); con->printf(" ");
+ con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
}
while (i < bpl)
{
j= width/4 + ((width%4)?1:0) + 1;
while (j)
{
- con->printf(" ");
+ con->dd_printf(" ");
j--;
}
i++;
i++)
{
long c= get(start+i);
- con->printf("%c", isprint(255&c)?(255&c):'.');
+ con->dd_printf("%c", isprint(255&c)?(255&c):'.');
if (width > 8)
- con->printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
+ con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
if (width > 16)
- con->printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
+ con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
if (width > 24)
- con->printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
+ con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
}
- con->printf("\n");
+ con->dd_printf("\n");
dump_finished= start+i;
start+= bpl;
}
* Bitmap
*/
-cl_bitmap::cl_bitmap(t_addr asize):
+/*cl_bitmap::cl_bitmap(t_addr asize):
cl_base()
{
map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
for (i= 0; i < size && map[i] == 0; i++) ;
return(i == size);
-}
+}*/
/*
* Special memory for code (ROM)
*/
-cl_rom::cl_rom(t_addr asize, int awidth):
- cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth)
+/*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)
{
bp_map= new cl_bitmap(asize);
inst_map= new cl_bitmap(asize);
{
delete bp_map;
delete inst_map;
+}*/
+
+
+/*
+ * New type of memory simulation
+ */
+
+cl_normal_cell::cl_normal_cell(uchar awidth):
+ cl_cell()
+{
+ type= CELL_NORMAL;
+ data= 0;
+ mask= 1;
+ width= awidth;
+ for (--awidth; awidth; awidth--)
+ {
+ mask<<= 1;
+ mask|= 1;
+ }
+}
+
+t_mem
+cl_normal_cell::add(long what)
+{
+ 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);
+}
+
+t_mem
+cl_normal_cell::wadd(long what)
+{
+ 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));
+}
+
+void
+cl_normal_cell::set_bit1(t_mem bits)
+{
+ bits&= mask;
+ data|= bits;
+}
+
+void
+cl_normal_cell::set_bit0(t_mem bits)
+{
+ bits&= mask;
+ data&= ~bits;
+}
+
+
+/*
+ */
+
+cl_registered_cell::cl_registered_cell(uchar awidth):
+ cl_normal_cell(awidth)
+{
+ type= CELL_HW_READ | CELL_HW_WRITE;
+ //hws= new cl_list(1, 1);
+ hardwares= 0;
+ nuof_hws= 0;
+}
+
+cl_registered_cell::~cl_registered_cell(void)
+{
+ if (hardwares)
+ free(hardwares);
+}
+
+/*void
+cl_registered_cell::destroy(void)
+{
+ hardwares= 0;
+ nuof_hws= 0;
+}*/
+
+t_mem
+cl_registered_cell::read(void)
+{
+ int i;
+ t_mem d= data;
+
+ if (nuof_hws)
+ for (i= 0; i < nuof_hws; i++)
+ {
+ d= hardwares[i]->read(this);
+ ;
+ }
+ return(d & mask);
+}
+
+t_mem
+cl_registered_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);
+ ;
+ }
+ return(d & mask);
+}
+
+t_mem
+cl_registered_cell::write(t_mem val)
+{
+ int i;
+
+ val&= mask;
+ if (nuof_hws)
+ for (i= 0; i < nuof_hws; i++)
+ {
+ hardwares[i]->write(this, &val);
+ ;
+ }
+ 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);
+}
+
+class cl_hw *
+cl_registered_cell::get_hw(int ith)
+{
+ if (ith >= nuof_hws)
+ return(0);
+ return(hardwares[ith]);
+}
+
+
+/*
+ */
+
+cl_event_handler::cl_event_handler(class cl_uc *auc):
+ cl_base()
+{
+ uc= auc;
+ read_bps= new cl_list(1, 1);
+ write_bps= new cl_list(1, 1);
+}
+
+cl_event_handler::~cl_event_handler(void)
+{
+ read_bps->disconn_all();
+ write_bps->disconn_all();
+ delete read_bps;
+ delete write_bps;
+}
+
+void
+cl_event_handler::write(void)
+{
+ 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);
+ }
+}
+
+void
+cl_event_handler::read(void)
+{
+ int i;
+
+ for (i= 0; i < read_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(read_bps->at(i));
+ uc->events->add(bp);
+ }
+}
+
+int
+cl_event_handler::add_bp(class cl_brk *bp)
+{
+ int t= CELL_NORMAL;
+
+ if (!bp)
+ return(CELL_NORMAL);
+ switch (bp->get_event())
+ {
+ 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;
+ }
+ return(t);
+}
+
+int
+cl_event_handler::copy_from(class cl_event_handler *eh)
+{
+ int i, t= CELL_NORMAL;
+
+ if (!eh)
+ return(t);
+ for (i= 0; i < eh->read_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i));
+ t|= add_bp(bp);
+ }
+ for (i= 0; i < eh->write_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i));
+ t|= add_bp(bp);
+ }
+ 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);
+}
+
+
+/*
+ */
+
+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)
+{
+ if (type & CELL_WRITE_BRK)
+ eh->write();
+ return(cl_normal_cell::write(val));
+}
+
+
+/*
+ */
+
+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)
+{
+ if (type & CELL_READ_BRK)
+ eh->read();
+ return(cl_registered_cell::read());
+}
+
+t_mem
+cl_ev_reg_cell::write(t_mem val)
+{
+ if (type & CELL_WRITE_BRK)
+ eh->write();
+ return(cl_registered_cell::write(val));
+}
+
+
+/*
+ */
+
+cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell)
+{
+ real_cell= realcell;
+}
+
+cl_mapped_cell::~cl_mapped_cell(void)
+{}
+
+t_mem
+cl_mapped_cell::read(void)
+{
+ return(real_cell->read());
+}
+
+t_mem
+cl_mapped_cell::read(enum hw_cath skip)
+{
+ return(real_cell->read(skip));
+}
+
+t_mem
+cl_mapped_cell::get(void)
+{
+ return(real_cell->get());
+}
+
+t_mem
+cl_mapped_cell::write(t_mem val)
+{
+ return(real_cell->write(val));
+}
+
+t_mem
+cl_mapped_cell::set(t_mem val)
+{
+ return(real_cell->set(val));
+}
+
+t_mem
+cl_mapped_cell::add(long what)
+{
+ return(real_cell->add(what));
+}
+
+t_mem
+cl_mapped_cell::wadd(long what)
+{
+ return(real_cell->wadd(what));
+}
+
+void
+cl_mapped_cell::set_bit1(t_mem bits)
+{
+ return(real_cell->set_bit1(bits));
+}
+
+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)
+{
+ 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;
+}
+
+void
+cl_m::err_inv_addr(t_addr addr)
+{
+ if (!uc)
+ return;
+ class cl_error *e= new cl_err_inv_addr(this, addr);
+ uc->error(e);
+}
+
+/*void
+cl_m::mk_cell(t_addr addr, class cl_cell *cell)
+{
+ 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
+ {
+ p->destroy();
+ p= (class cl_cell *)realloc(p, sizeof(cell));
+ }
+ memcpy(p, cell, sizeof(*cell));
+ cell->destroy();
+ delete cell;
+}*/
+
+int
+cl_m::get_cell_flag(t_addr addr)
+{
+ if (addr >= size)
+ {
+ return(dummy->get_type());
+ }
+ return(array[addr]->get_type());
+}
+
+bool
+cl_m::get_cell_flag(t_addr addr, int flag)
+{
+ if (addr >= size)
+ {
+ return(dummy->get_type() & flag);
+ }
+ return(array[addr]->get_type() & flag);
+}
+
+void
+cl_m::set_cell_flag(t_addr addr, bool set_to, int flag)
+{
+ class cl_cell *cell;
+
+ if (addr >= size)
+ {
+ cell= dummy;
+ }
+ else
+ cell= array[addr];
+ if (set_to)
+ cell->set_type(cell->get_type() | flag);
+ else
+ cell->set_type(cell->get_type() & ~flag);
+}
+
+t_mem
+cl_m::read(t_addr addr)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->read());
+ }
+ return(array[addr]->read());
+}
+
+t_mem
+cl_m::read(t_addr addr, enum hw_cath skip)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->read(skip));
+ }
+ return(array[addr]->read(skip));
+}
+
+t_mem
+cl_m::get(t_addr addr)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->get());
+ }
+ return(array[addr]->get());
+}
+
+t_mem
+cl_m::write(t_addr addr, t_mem val)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->write(val));
+ }
+ return(array[addr]->write(val));
+}
+
+void
+cl_m::set(t_addr addr, t_mem val)
+{
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ //addr&= bus_mask;
+ dummy->set(val);
+ return;
+ }
+ //addr&= bus_mask;
+ array[addr]->set(val);
+}
+
+class cl_cell *
+cl_m::get_cell(t_addr addr)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy);
+ }
+ return(array[addr]);
+}
+
+
+/* Set or clear bits, without callbacks */
+
+void
+cl_m::set_bit1(t_addr addr, t_mem bits)
+{
+ 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);
+}
+
+void
+cl_m::write_bit1(t_addr addr, t_mem bits)
+{
+ 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->write(cell->get() | bits);
+}
+
+void
+cl_m::set_bit0(t_addr addr, t_mem bits)
+{
+ 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);
+}
+
+void
+cl_m::write_bit0(t_addr addr, t_mem bits)
+{
+ 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->write(cell->get() & ~bits);
+}
+
+t_mem
+cl_m::add(t_addr addr, long what)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->add(what));
+ }
+ return(array[addr]->add(what));
+}
+
+t_mem
+cl_m::wadd(t_addr addr, long what)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->wadd(what));
+ }
+ return(array[addr]->wadd(what));
+}
+
+class cl_cell *
+cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce)
+{
+ class cl_cell *cell, *nc;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ cell= dummy;
+ else
+ cell= array[addr];
+
+ 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;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ if (announce)
+ uc->sim->/*app->*/mem_cell_changed(this, addr);
+ return(nc);
+}
+
+void
+cl_m::set_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())
+ {
+ 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;
+ }
+
+ if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
+ {
+ /* 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));
+ }
+ else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
+ {
+ /* 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;
+ }
+ else
+ {
+ /* 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));
+ }
+
+ if (addr >= size)
+ {
+ delete dummy;
+ dummy= nc;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ 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())
+ {
+ 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;
+ }
+
+ if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
+ {
+ /* 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))
+ {
+ cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
+ cell->set_type(cell->get_type() | t);
+ return;
+ }
+ 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))
+ {
+ /* 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;
+ }
+ else
+ {
+ /* Normal cell */
+ return;
+ }
+
+ if (addr >= size)
+ {
+ delete dummy;
+ dummy= nc;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ uc->sim->/*app->*/mem_cell_changed(this, addr);
+}
+
+
+/*
+ * Errors in memory handling
+ */
+
+cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr):
+ cl_error()
+{
+ mem= amem;
+ addr= aaddr;
+}
+
+void
+cl_err_inv_addr::print(class cl_commander *c)
+{
+ c->dd_printf("Error: invalid address ");
+ c->dd_printf(mem->addr_format, addr);
+ c->dd_printf(" in memory %s.\n", mem->class_name);
}