2 * Simulator of microcontrollers (mem.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
11 This file is part of microcontroller simulator: ucsim.
13 UCSIM is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 UCSIM is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with UCSIM; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
52 * 3rd version of memory system
55 cl_memory::cl_memory(char *id, t_addr asize, int awidth):
60 addr_format= data_format= 0;
66 cl_memory::~cl_memory(void)
77 addr_format= (char *)malloc(10);
78 sprintf(addr_format, "0x%%0%dx",
84 (size-1<=0xffffff?6:12))))));
85 data_format= (char *)malloc(10);
86 sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
94 dump_finished= start_address;
100 cl_memory::valid_address(t_addr addr)
102 return(addr >= start_address &&
103 addr < start_address+size);
107 cl_memory::inc_address(t_addr addr, int val)
110 return(((signed)addr+val)%size);
111 addr-= start_address;
114 addr+= start_address;
119 cl_memory::inc_address(t_addr addr)
122 return(((signed)addr+1)%size);
123 addr-= start_address;
126 addr+= start_address;
131 cl_memory::validate_address(t_addr addr)
133 while (addr < start_address)
135 if (addr > start_address+size)
137 addr-= start_address;
139 addr+= start_address;
146 cl_memory::err_inv_addr(t_addr addr)
150 class cl_error *e= new cl_error_mem_invalid_address(this, addr);
155 cl_memory::err_non_decoded(t_addr addr)
159 class cl_error *e= new cl_error_mem_non_decoded(this, addr);
165 cl_memory::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
168 t_addr lva= lowest_valid_address();
169 t_addr hva= highest_valid_address();
175 while ((start <= stop) &&
178 con->dd_printf(addr_format, start); con->dd_printf(" ");
185 con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
190 j= width/4 + ((width%4)?1:0) + 1;
198 for (i= 0; (i < bpl) &&
203 long c= read(start+i);
204 con->dd_printf("%c", isprint(255&c)?(255&c):'.');
206 con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
208 con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
210 con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
212 con->dd_printf("\n");
213 dump_finished= start+i;
216 return(dump_finished);
220 cl_memory::dump(class cl_console *con)
222 return(dump(dump_finished, dump_finished+10*8-1, 8, con));
226 cl_memory::search_next(bool case_sensitive,
227 t_mem *array, int len, t_addr *addr)
246 for (i= 0; i < len && match; i++)
253 if (/*d1 < 128*/isalpha(d1))
255 if (/*d2 < 128*/isalpha(d2))
275 cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell,
286 cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell,
288 t_mem *data_place, t_mem the_mask):
299 cl_memory_operator::set_data(t_mem *data_place, t_mem the_mask)
307 cl_memory_operator::read(void)
310 return(next_operator->read());
316 cl_memory_operator::write(t_mem val)
319 return(next_operator->write(val));
321 return(*data= (val & mask));
325 /* Memory operator for hw callbacks */
327 cl_hw_operator::cl_hw_operator(class cl_memory_cell *acell, t_addr addr,
328 t_mem *data_place, t_mem the_mask,
330 cl_memory_operator(acell, addr, data_place, the_mask)
337 cl_hw_operator::read(void)
345 next_operator->read();
351 cl_hw_operator::read(enum hw_cath skip)
356 hw->cathegory != skip)
360 next_operator->read();
366 cl_hw_operator::write(t_mem val)
369 hw->write(cell, &val);
371 val= next_operator->write(val);
372 return(*data= (val & mask));
376 /* Write event break on cell */
378 cl_write_operator::cl_write_operator(class cl_memory_cell *acell, t_addr addr,
379 t_mem *data_place, t_mem the_mask,
380 class cl_uc *auc, class cl_brk *the_bp):
381 cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp)
388 cl_write_operator::write(t_mem val)
390 //printf("write event at 0x%x bp=%p\n",address,bp);
393 return(next_operator->write(val));
395 return(*data= (val & mask));
399 /* Read event break on cell */
401 cl_read_operator::cl_read_operator(class cl_memory_cell *acell, t_addr addr,
402 t_mem *data_place, t_mem the_mask,
403 class cl_uc *auc, class cl_brk *the_bp):
404 cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp)
411 cl_read_operator::read(void)
413 //printf("read event at 0x%x bp=%p\n",address,bp);
416 return(next_operator->read());
426 cl_memory_cell::cl_memory_cell(void):
429 data= (t_mem *)malloc(sizeof(t_mem));
430 flags= CELL_NON_DECODED;
435 nuof_writes= nuof_reads= 0;
447 cl_memory_cell::~cl_memory_cell(void)
449 if ((flags & CELL_NON_DECODED) &&
455 cl_memory_cell::init(void)
464 cl_memory_cell::get_flags(void)
470 cl_memory_cell::get_flag(enum cell_flag flag)
472 return(flags & flag);
476 cl_memory_cell::set_flags(TYPE_UBYTE what)
482 cl_memory_cell::set_flag(enum cell_flag flag, bool val)
492 cl_memory_cell::un_decode(void)
494 if ((flags & CELL_NON_DECODED) == 0)
496 data= (t_mem *)malloc(sizeof(t_mem));
497 flags|= CELL_NON_DECODED;
502 cl_memory_cell::decode(class cl_memory_chip *chip, t_addr addr)
504 if (flags & CELL_NON_DECODED)
506 data= chip->get_slot(addr);
509 data= (t_mem *)malloc(sizeof(t_mem));
510 flags|= CELL_NON_DECODED;
513 flags&= ~(CELL_NON_DECODED);
518 cl_memory_cell::read(void)
524 return(operators->read());
529 cl_memory_cell::read(enum hw_cath skip)
535 return(operators->read(skip));
540 cl_memory_cell::get(void)
546 cl_memory_cell::write(t_mem val)
552 return(operators->write(val));
558 cl_memory_cell::set(t_mem val)
567 cl_memory_cell::add(long what)
569 *data= (*data + what) & mask;
574 cl_memory_cell::wadd(long what)
576 t_mem d= (*data + what) & mask;
581 cl_memory_cell::set_bit1(t_mem bits)
588 cl_memory_cell::set_bit0(t_mem bits)
596 cl_memory_cell::append_operator(class cl_memory_operator *op)
602 class cl_memory_operator *o= operators, *n;
614 cl_memory_cell::prepend_operator(class cl_memory_operator *op)
618 op->set_next(operators);
624 cl_memory_cell::del_operator(class cl_brk *brk)
628 class cl_memory_operator *op= operators;
629 if (operators->match(brk))
631 operators= op->get_next();
636 while (op->get_next() &&
637 !op->get_next()->match(brk))
641 class cl_memory_operator *m= op->get_next();
642 op->set_next(m->get_next());;
649 class cl_memory_cell *
650 cl_memory_cell::add_hw(class cl_hw *hw, int *ith, t_addr addr)
652 class cl_hw_operator *o= new cl_hw_operator(this, addr, data, mask, hw);
658 cl_memory_cell::get_hw(int ith)
663 class cl_event_handler *
664 cl_memory_cell::get_event_handler(void)
671 * Dummy cell for non-existent addresses
675 cl_dummy_cell::write(t_mem val)
680 *data= rand() & mask;
685 cl_dummy_cell::set(t_mem val)
687 *data= rand() & mask;
696 cl_address_space::cl_address_space(char *id,
697 t_addr astart, t_addr asize, int awidth):
698 cl_memory(id, asize, awidth)
700 start_address= astart;
701 decoders= new cl_decoder_list(2, 2, DD_FALSE);
702 cells= (class cl_memory_cell **)malloc(size * sizeof(class cl_memory_cell*));
704 for (i= 0; i < size; i++)
706 cells[i]= new cl_memory_cell();
709 dummy= new cl_dummy_cell();
712 cl_address_space::~cl_address_space(void)
716 for (i= 0; i < size; i++)
724 cl_address_space::read(t_addr addr)
726 t_addr idx= addr-start_address;
728 addr < start_address)
731 return(dummy->read());
733 return(cells[idx]->read());
737 cl_address_space::read(t_addr addr, enum hw_cath skip)
739 t_addr idx= addr-start_address;
741 addr < start_address)
744 return(dummy->read());
746 return(cells[idx]->read(skip));
750 cl_address_space::get(t_addr addr)
752 t_addr idx= addr-start_address;
754 addr < start_address)
757 return(dummy->get());
759 return(cells[idx]->get());
763 cl_address_space::write(t_addr addr, t_mem val)
765 t_addr idx= addr-start_address;
767 addr < start_address)
770 return(dummy->write(val));
772 return(cells[idx]->write(val));
776 cl_address_space::set(t_addr addr, t_mem val)
778 t_addr idx= addr-start_address;
780 addr < start_address)
786 cells[idx]->set(val);
790 cl_address_space::wadd(t_addr addr, long what)
792 t_addr idx= addr-start_address;
794 addr < start_address)
798 return(cells[idx]->wadd(what));
801 /* Set or clear bits, without callbacks */
804 cl_address_space::set_bit1(t_addr addr, t_mem bits)
806 t_addr idx= addr-start_address;
808 addr < start_address)
810 class cl_memory_cell *cell= cells[idx];
811 cell->set_bit1(bits);
815 cl_address_space::set_bit0(t_addr addr, t_mem bits)
817 t_addr idx= addr-start_address;
819 addr < start_address)
821 class cl_memory_cell *cell= cells[idx];
822 cell->set_bit0(bits);
826 class cl_memory_cell *
827 cl_address_space::get_cell(t_addr addr)
829 t_addr idx= addr-start_address;
831 addr < start_address)
841 cl_address_space::get_cell_flag(t_addr addr)
843 t_addr idx= addr-start_address;
845 addr < start_address)
847 return(dummy->get_flags());
849 return(cells[addr]->get_flags());
853 cl_address_space::get_cell_flag(t_addr addr, enum cell_flag flag)
855 t_addr idx= addr-start_address;
857 addr < start_address)
859 return(dummy->get_flag(flag));
861 return(cells[addr]->get_flag(flag));
865 cl_address_space::set_cell_flag(t_addr addr, bool set_to, enum cell_flag flag)
867 t_addr idx= addr-start_address;
868 class cl_memory_cell *cell;
871 addr < start_address)
877 cell->set_flag(flag, set_to);
882 cl_address_space::decode_cell(t_addr addr,
883 class cl_memory_chip *chip, t_addr chipaddr)
885 t_addr idx= addr-start_address;
887 addr < start_address)
889 class cl_memory_cell *cell= cells[idx];
891 if (!cell->get_flag(CELL_NON_DECODED))
896 cell->decode(chip, chipaddr);
898 return(!cell->get_flag(CELL_NON_DECODED));
902 cl_address_space::undecode_cell(t_addr addr)
904 t_addr idx= addr-start_address;
906 addr < start_address)
908 class cl_memory_cell *cell= cells[idx];
914 cl_address_space::undecode_area(class cl_address_decoder *skip,
915 t_addr begin, t_addr end,class cl_console *con)
917 #define D if (con) con->debug
918 D("Undecoding area 0x%x-0x%x of %s\n", begin, end, get_name());
920 for (i= 0; i < decoders->count; i++)
922 class cl_address_decoder *d=
923 dynamic_cast<class cl_address_decoder *>(decoders->object_at(i));
927 D(" Checking decoder 0x%x-0x%x -> %s[0x%x]\n",
928 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
929 if (d->fully_covered_by(begin, end))
931 // decoder can be removed
932 D(" Can be removed\n");
933 decoders->disconn(d);
936 if (decoders->count == 0)
939 else if (d->covers(begin, end))
941 // decoder must be split
942 D(" Must be split\n");
943 class cl_address_decoder *nd= d->split(begin, end);
944 D(" After split:\n");
945 D(" 0x%x-0x%x -> %s[0x%x]\n",
946 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
950 D(" 0x%x-0x%x -> %s[0x%x]\n",
951 nd->as_begin, nd->as_end, nd->memchip->get_name(), nd->chip_begin);
955 else if (d->is_in(begin, end))
957 // decoder sould shrink
958 D(" Sould shrink\n");
959 if (d->shrink_out_of(begin, end))
961 D(" Can be removed after shrink\n");
962 decoders->disconn(d);
965 if (decoders->count == 0)
970 D(" Shrinked to 0x%x-0x%x -> %s[0x%x]\n",
971 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
979 class cl_memory_cell *
980 cl_address_space::register_hw(t_addr addr, class cl_hw *hw,
984 t_addr idx= addr-start_address;
986 addr < start_address)
988 class cl_memory_cell *cell= cells[idx];
989 cell->add_hw(hw, ith, addr);
990 //printf("adding hw %s to cell 0x%x(%d) of %s\n", hw->id_string, addr, idx, get_name("as"));
992 ;//uc->sim->/*app->*/mem_cell_changed(this, addr);//FIXME
998 cl_address_space::set_brk(t_addr addr, class cl_brk *brk)
1000 t_addr idx= addr-start_address;
1002 addr < start_address)
1004 class cl_memory_cell *cell= cells[idx];
1005 class cl_memory_operator *op;
1007 switch (brk->get_event())
1009 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1011 op= new cl_write_operator(cell, addr, cell->get_data(), cell->get_mask(),
1014 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1016 op= new cl_read_operator(cell, addr, cell->get_data(), cell->get_mask(),
1020 set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
1029 cell->append_operator(op);
1033 cl_address_space::del_brk(t_addr addr, class cl_brk *brk)
1035 t_addr idx= addr-start_address;
1037 addr < start_address)
1039 class cl_memory_cell *cell= cells[idx];
1041 switch (brk->get_event())
1043 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1044 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1045 cell->del_operator(brk);
1048 set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
1058 * List of address spaces
1061 cl_address_space_list::cl_address_space_list(class cl_uc *the_uc):
1062 cl_list(2, 2, "address spaces")
1068 cl_address_space_list::add(class cl_address_space *mem)
1071 t_index ret= cl_list::add(mem);
1074 class cl_event_address_space_added e(mem);
1075 uc->handle_event(e);
1085 cl_memory_chip::cl_memory_chip(char *id, int asize, int awidth, int initial):
1086 cl_memory(id, asize, awidth)
1088 array= (t_mem *)malloc(size * sizeof(t_mem));
1089 init_value= initial;
1092 cl_memory_chip::~cl_memory_chip(void)
1099 cl_memory_chip::init(void)
1103 for (i= 0; i < size; i++)
1105 (init_value<0)?rand():(init_value));
1111 cl_memory_chip::get_slot(t_addr addr)
1116 return(&array[addr]);
1121 cl_memory_chip::get(t_addr addr)
1126 return(array[addr]);
1130 cl_memory_chip::set(t_addr addr, t_mem val)
1135 array[addr]= val & data_mask;
1139 cl_memory_chip::set_bit1(t_addr addr, t_mem bits)
1144 array[addr]|= (bits & data_mask);
1148 cl_memory_chip::set_bit0(t_addr addr, t_mem bits)
1153 array[addr]&= ((~bits) & data_mask);
1161 cl_address_decoder::cl_address_decoder(class cl_memory *as,
1162 class cl_memory *chip,
1163 t_addr asb, t_addr ase, t_addr cb)
1165 if (as->is_address_space())
1166 address_space= (class cl_address_space *)as;
1169 if (chip->is_chip())
1170 memchip= (class cl_memory_chip *)chip;
1176 activated= DD_FALSE;
1179 cl_address_decoder::~cl_address_decoder(void)
1183 for (a= as_begin; a <= as_end; a++)
1184 address_space->undecode_cell(a);
1188 cl_address_decoder::init(void)
1195 cl_address_decoder::activate(class cl_console *con)
1197 #define D if (con) con->debug
1198 D("Activation of an address decoder\n");
1201 D("Already activated\n");
1204 if (!address_space ||
1205 !address_space->is_address_space())
1207 D("No or non address space\n");
1211 !memchip->is_chip())
1213 D("No or non memory chip\n");
1216 if (as_begin > as_end)
1218 D("Wrong address area specification\n");
1221 if (chip_begin >= memchip->get_size())
1223 D("Wrong chip area specification\n");
1226 if (as_begin < address_space->start_address ||
1227 as_end >= address_space->start_address + address_space->get_size())
1229 D("Specified area is out of address space\n");
1232 if (as_end-as_begin > memchip->get_size()-chip_begin)
1234 D("Specified area is out of chip size\n");
1238 address_space->undecode_area(this, as_begin, as_end, con);
1241 for (asa= as_begin, ca= chip_begin;
1245 if (!address_space->decode_cell(asa, memchip, ca))
1247 D("Decoding 0x%06x->0x%06x failed\n", asa, ca);
1258 cl_address_decoder::fully_covered_by(t_addr begin, t_addr end)
1260 if (begin <= as_begin &&
1267 cl_address_decoder::is_in(t_addr begin, t_addr end)
1269 if (begin >= as_begin &&
1272 if (end >= as_begin &&
1279 cl_address_decoder::covers(t_addr begin, t_addr end)
1281 if (begin > as_begin &&
1288 /* Returns TRUE if shrunken decoder is unnecessary */
1291 cl_address_decoder::shrink_out_of(t_addr begin, t_addr end)
1302 address_space->undecode_cell(a);
1305 if (begin > as_begin)
1309 chip_begin+= (end-as_begin+1);
1312 if (as_end < as_begin)
1317 class cl_address_decoder *
1318 cl_address_decoder::split(t_addr begin, t_addr end)
1320 class cl_address_decoder *nd= 0;
1321 if (begin > as_begin)
1324 nd= new cl_address_decoder(address_space, memchip,
1325 end+1, as_end, chip_begin+(end-as_begin)+1);
1326 shrink_out_of(begin, as_end);
1328 else if (end < as_end)
1330 if (as_begin < begin)
1331 nd= new cl_address_decoder(address_space, memchip,
1332 as_begin, begin-1, chip_begin);
1333 shrink_out_of(end+1, as_end);
1342 * List of address decoders
1345 cl_decoder_list::cl_decoder_list(t_index alimit, t_index adelta, bool bychip):
1346 cl_sorted_list(alimit, adelta, "decoder list")
1348 Duplicates= DD_TRUE;
1353 cl_decoder_list::key_of(void *item)
1355 class cl_address_decoder *d= (class cl_address_decoder *)item;
1357 return(&(d->chip_begin));
1359 return(&(d->as_begin));
1363 cl_decoder_list::compare(void *key1, void *key2)
1365 t_addr k1= *((t_addr*)key1), k2= *((t_addr*)key2);
1375 * Errors in memory handling
1378 /* All of memory errors */
1379 ERROR_CLASS_DEF_PARENT_ON(err_error, mem, "memory",
1380 error_class_base, ERROR_ON);
1382 cl_error_mem::cl_error_mem(class cl_memory *amem, t_addr aaddr)
1386 classification= &error_mem_class;
1389 /* Invalid address in memory access */
1390 ERROR_CLASS_DEF_PARENT(err_error,
1391 mem_invalid_address,
1395 cl_error_mem_invalid_address::
1396 cl_error_mem_invalid_address(class cl_memory *amem, t_addr aaddr):
1397 cl_error_mem(amem, aaddr)
1399 classification= &error_mem_invalid_address_class;
1403 cl_error_mem_invalid_address::print(class cl_commander *c)
1405 FILE *f= c->get_out();
1406 cmd_fprintf(f, "%s: invalid address ", get_type_name());
1407 cmd_fprintf(f, mem->addr_format, addr);
1408 cmd_fprintf(f, " in memory %s.\n", mem->get_name());
1411 /* Non-decoded address space access */
1412 ERROR_CLASS_DEF_PARENT(err_error,
1417 cl_error_mem_non_decoded::
1418 cl_error_mem_non_decoded(class cl_memory *amem, t_addr aaddr):
1419 cl_error_mem(amem, aaddr)
1421 classification= &error_mem_non_decoded_class;
1425 cl_error_mem_non_decoded::print(class cl_commander *c)
1427 FILE *f= c->get_out();
1428 cmd_fprintf(f, "%s: access of non-decoded address ", get_type_name());
1429 cmd_fprintf(f, mem->addr_format, addr);
1430 cmd_fprintf(f, " in memory %s.\n", mem->get_name());