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
51 * 3rd version of memory system
54 cl_memory::cl_memory(char *id, t_addr asize, int awidth):
59 addr_format= data_format= 0;
65 cl_memory::~cl_memory(void)
76 addr_format= (char *)malloc(10);
77 sprintf(addr_format, "0x%%0%dx",
83 (size-1<=0xffffff?6:12))))));
84 data_format= (char *)malloc(10);
85 sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
93 dump_finished= start_address;
99 cl_memory::valid_address(t_addr addr)
101 return(addr >= start_address &&
102 addr < start_address+size);
106 cl_memory::inc_address(t_addr addr, int val)
109 return(((signed)addr+val)%size);
110 addr-= start_address;
113 addr+= start_address;
118 cl_memory::inc_address(t_addr addr)
121 return(((signed)addr+1)%size);
122 addr-= start_address;
125 addr+= start_address;
130 cl_memory::validate_address(t_addr addr)
132 while (addr < start_address)
134 if (addr > start_address+size)
136 addr-= start_address;
138 addr+= start_address;
145 cl_memory::err_inv_addr(t_addr addr)
149 class cl_error *e= new cl_error_mem_invalid_address(this, addr);
154 cl_memory::err_non_decoded(t_addr addr)
158 class cl_error *e= new cl_error_mem_non_decoded(this, addr);
164 cl_memory::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
167 t_addr lva= lowest_valid_address();
168 t_addr hva= highest_valid_address();
174 while ((start <= stop) &&
177 con->dd_printf(addr_format, start); con->dd_printf(" ");
184 con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
189 j= width/4 + ((width%4)?1:0) + 1;
197 for (i= 0; (i < bpl) &&
202 long c= read(start+i);
203 con->dd_printf("%c", isprint(255&c)?(255&c):'.');
205 con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
207 con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
209 con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
211 con->dd_printf("\n");
212 dump_finished= start+i;
215 return(dump_finished);
219 cl_memory::dump(class cl_console *con)
221 return(dump(dump_finished, dump_finished+10*8-1, 8, con));
225 cl_memory::search_next(bool case_sensitive,
226 t_mem *array, int len, t_addr *addr)
245 for (i= 0; i < len && match; i++)
252 if (/*d1 < 128*/isalpha(d1))
254 if (/*d2 < 128*/isalpha(d2))
274 cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell,
285 cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell,
287 t_mem *data_place, t_mem the_mask):
298 cl_memory_operator::set_data(t_mem *data_place, t_mem the_mask)
306 cl_memory_operator::read(void)
309 return(next_operator->read());
315 cl_memory_operator::write(t_mem val)
318 return(next_operator->write(val));
320 return(*data= (val & mask));
324 /* Memory operator for hw callbacks */
326 cl_hw_operator::cl_hw_operator(class cl_memory_cell *acell, t_addr addr,
327 t_mem *data_place, t_mem the_mask,
329 cl_memory_operator(acell, addr, data_place, the_mask)
336 cl_hw_operator::read(void)
344 next_operator->read();
350 cl_hw_operator::read(enum hw_cath skip)
355 hw->cathegory != skip)
359 next_operator->read();
365 cl_hw_operator::write(t_mem val)
368 hw->write(cell, &val);
370 val= next_operator->write(val);
371 return(*data= (val & mask));
375 /* Write event break on cell */
377 cl_write_operator::cl_write_operator(class cl_memory_cell *acell, t_addr addr,
378 t_mem *data_place, t_mem the_mask,
379 class cl_uc *auc, class cl_brk *the_bp):
380 cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp)
387 cl_write_operator::write(t_mem val)
389 //printf("write event at 0x%x bp=%p\n",address,bp);
392 return(next_operator->write(val));
394 return(*data= (val & mask));
398 /* Read event break on cell */
400 cl_read_operator::cl_read_operator(class cl_memory_cell *acell, t_addr addr,
401 t_mem *data_place, t_mem the_mask,
402 class cl_uc *auc, class cl_brk *the_bp):
403 cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp)
410 cl_read_operator::read(void)
412 //printf("read event at 0x%x bp=%p\n",address,bp);
415 return(next_operator->read());
425 cl_memory_cell::cl_memory_cell(void):
428 data= (t_mem *)malloc(sizeof(t_mem));
429 flags= CELL_NON_DECODED;
434 nuof_writes= nuof_reads= 0;
446 cl_memory_cell::~cl_memory_cell(void)
448 if ((flags & CELL_NON_DECODED) &&
454 cl_memory_cell::init(void)
463 cl_memory_cell::get_flags(void)
469 cl_memory_cell::get_flag(enum cell_flag flag)
471 return(flags & flag);
475 cl_memory_cell::set_flags(TYPE_UBYTE what)
481 cl_memory_cell::set_flag(enum cell_flag flag, bool val)
491 cl_memory_cell::un_decode(void)
493 if ((flags & CELL_NON_DECODED) == 0)
495 data= (t_mem *)malloc(sizeof(t_mem));
496 flags|= CELL_NON_DECODED;
501 cl_memory_cell::decode(class cl_memory_chip *chip, t_addr addr)
503 if (flags & CELL_NON_DECODED)
505 data= chip->get_slot(addr);
508 data= (t_mem *)malloc(sizeof(t_mem));
509 flags|= CELL_NON_DECODED;
512 flags&= ~(CELL_NON_DECODED);
517 cl_memory_cell::read(void)
523 return(operators->read());
528 cl_memory_cell::read(enum hw_cath skip)
534 return(operators->read(skip));
539 cl_memory_cell::get(void)
545 cl_memory_cell::write(t_mem val)
551 return(operators->write(val));
557 cl_memory_cell::set(t_mem val)
566 cl_memory_cell::add(long what)
568 *data= (*data + what) & mask;
573 cl_memory_cell::wadd(long what)
575 t_mem d= (*data + what) & mask;
580 cl_memory_cell::set_bit1(t_mem bits)
587 cl_memory_cell::set_bit0(t_mem bits)
595 cl_memory_cell::append_operator(class cl_memory_operator *op)
601 class cl_memory_operator *o= operators, *n;
613 cl_memory_cell::prepend_operator(class cl_memory_operator *op)
617 op->set_next(operators);
623 cl_memory_cell::del_operator(class cl_brk *brk)
627 class cl_memory_operator *op= operators;
628 if (operators->match(brk))
630 operators= op->get_next();
635 while (op->get_next() &&
636 !op->get_next()->match(brk))
640 class cl_memory_operator *m= op->get_next();
641 op->set_next(m->get_next());;
648 class cl_memory_cell *
649 cl_memory_cell::add_hw(class cl_hw *hw, int *ith, t_addr addr)
651 class cl_hw_operator *o= new cl_hw_operator(this, addr, data, mask, hw);
657 cl_memory_cell::get_hw(int ith)
662 class cl_event_handler *
663 cl_memory_cell::get_event_handler(void)
670 * Dummy cell for non-existent addresses
674 cl_dummy_cell::write(t_mem val)
679 *data= rand() & mask;
684 cl_dummy_cell::set(t_mem val)
686 *data= rand() & mask;
695 cl_address_space::cl_address_space(char *id,
696 t_addr astart, t_addr asize, int awidth):
697 cl_memory(id, asize, awidth)
699 start_address= astart;
700 decoders= new cl_decoder_list(2, 2, DD_FALSE);
701 cells= (class cl_memory_cell **)malloc(size * sizeof(class cl_memory_cell*));
703 for (i= 0; i < size; i++)
705 cells[i]= new cl_memory_cell();
708 dummy= new cl_dummy_cell();
711 cl_address_space::~cl_address_space(void)
715 for (i= 0; i < size; i++)
723 cl_address_space::read(t_addr addr)
725 t_addr idx= addr-start_address;
727 addr < start_address)
730 return(dummy->read());
732 return(cells[idx]->read());
736 cl_address_space::read(t_addr addr, enum hw_cath skip)
738 t_addr idx= addr-start_address;
740 addr < start_address)
743 return(dummy->read());
745 return(cells[idx]->read(skip));
749 cl_address_space::get(t_addr addr)
751 t_addr idx= addr-start_address;
753 addr < start_address)
756 return(dummy->get());
758 return(cells[idx]->get());
762 cl_address_space::write(t_addr addr, t_mem val)
764 t_addr idx= addr-start_address;
766 addr < start_address)
769 return(dummy->write(val));
771 return(cells[idx]->write(val));
775 cl_address_space::set(t_addr addr, t_mem val)
777 t_addr idx= addr-start_address;
779 addr < start_address)
785 cells[idx]->set(val);
789 cl_address_space::wadd(t_addr addr, long what)
791 t_addr idx= addr-start_address;
793 addr < start_address)
797 return(cells[idx]->wadd(what));
800 /* Set or clear bits, without callbacks */
803 cl_address_space::set_bit1(t_addr addr, t_mem bits)
805 t_addr idx= addr-start_address;
807 addr < start_address)
809 class cl_memory_cell *cell= cells[idx];
810 cell->set_bit1(bits);
814 cl_address_space::set_bit0(t_addr addr, t_mem bits)
816 t_addr idx= addr-start_address;
818 addr < start_address)
820 class cl_memory_cell *cell= cells[idx];
821 cell->set_bit0(bits);
825 class cl_memory_cell *
826 cl_address_space::get_cell(t_addr addr)
828 t_addr idx= addr-start_address;
830 addr < start_address)
840 cl_address_space::get_cell_flag(t_addr addr)
842 t_addr idx= addr-start_address;
844 addr < start_address)
846 return(dummy->get_flags());
848 return(cells[addr]->get_flags());
852 cl_address_space::get_cell_flag(t_addr addr, enum cell_flag flag)
854 t_addr idx= addr-start_address;
856 addr < start_address)
858 return(dummy->get_flag(flag));
860 return(cells[addr]->get_flag(flag));
864 cl_address_space::set_cell_flag(t_addr addr, bool set_to, enum cell_flag flag)
866 t_addr idx= addr-start_address;
867 class cl_memory_cell *cell;
870 addr < start_address)
876 cell->set_flag(flag, set_to);
881 cl_address_space::decode_cell(t_addr addr,
882 class cl_memory_chip *chip, t_addr chipaddr)
884 t_addr idx= addr-start_address;
886 addr < start_address)
888 class cl_memory_cell *cell= cells[idx];
890 if (!cell->get_flag(CELL_NON_DECODED))
895 cell->decode(chip, chipaddr);
897 return(!cell->get_flag(CELL_NON_DECODED));
901 cl_address_space::undecode_cell(t_addr addr)
903 t_addr idx= addr-start_address;
905 addr < start_address)
907 class cl_memory_cell *cell= cells[idx];
913 cl_address_space::undecode_area(class cl_address_decoder *skip,
914 t_addr begin, t_addr end,class cl_console *con)
916 #define D if (con) con->debug
917 D("Undecoding area 0x%x-0x%x of %s\n", begin, end, get_name());
919 for (i= 0; i < decoders->count; i++)
921 class cl_address_decoder *d=
922 dynamic_cast<class cl_address_decoder *>(decoders->object_at(i));
926 D(" Checking decoder 0x%x-0x%x -> %s[0x%x]\n",
927 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
928 if (d->fully_covered_by(begin, end))
930 // decoder can be removed
931 D(" Can be removed\n");
932 decoders->disconn(d);
935 if (decoders->count == 0)
938 else if (d->covers(begin, end))
940 // decoder must be split
941 D(" Must be split\n");
942 class cl_address_decoder *nd= d->split(begin, end);
943 D(" After split:\n");
944 D(" 0x%x-0x%x -> %s[0x%x]\n",
945 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
949 D(" 0x%x-0x%x -> %s[0x%x]\n",
950 nd->as_begin, nd->as_end, nd->memchip->get_name(), nd->chip_begin);
954 else if (d->is_in(begin, end))
956 // decoder sould shrink
957 D(" Sould shrink\n");
958 if (d->shrink_out_of(begin, end))
960 D(" Can be removed after shrink\n");
961 decoders->disconn(d);
964 if (decoders->count == 0)
969 D(" Shrinked to 0x%x-0x%x -> %s[0x%x]\n",
970 d->as_begin, d->as_end, d->memchip->get_name(), d->chip_begin);
978 class cl_memory_cell *
979 cl_address_space::register_hw(t_addr addr, class cl_hw *hw,
983 t_addr idx= addr-start_address;
985 addr < start_address)
987 class cl_memory_cell *cell= cells[idx];
988 cell->add_hw(hw, ith, addr);
989 //printf("adding hw %s to cell 0x%x(%d) of %s\n", hw->id_string, addr, idx, get_name("as"));
991 ;//uc->sim->/*app->*/mem_cell_changed(this, addr);//FIXME
997 cl_address_space::set_brk(t_addr addr, class cl_brk *brk)
999 t_addr idx= addr-start_address;
1001 addr < start_address)
1003 class cl_memory_cell *cell= cells[idx];
1004 class cl_memory_operator *op;
1006 switch (brk->get_event())
1008 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1010 op= new cl_write_operator(cell, addr, cell->get_data(), cell->get_mask(),
1013 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1015 op= new cl_read_operator(cell, addr, cell->get_data(), cell->get_mask(),
1019 set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
1028 cell->append_operator(op);
1032 cl_address_space::del_brk(t_addr addr, class cl_brk *brk)
1034 t_addr idx= addr-start_address;
1036 addr < start_address)
1038 class cl_memory_cell *cell= cells[idx];
1040 switch (brk->get_event())
1042 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1043 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1044 cell->del_operator(brk);
1047 set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
1057 * List of address spaces
1060 cl_address_space_list::cl_address_space_list(class cl_uc *the_uc):
1061 cl_list(2, 2, "address spaces")
1067 cl_address_space_list::add(class cl_address_space *mem)
1070 t_index ret= cl_list::add(mem);
1073 class cl_event_address_space_added e(mem);
1074 uc->handle_event(e);
1084 cl_memory_chip::cl_memory_chip(char *id, int asize, int awidth, int initial):
1085 cl_memory(id, asize, awidth)
1087 array= (t_mem *)malloc(size * sizeof(t_mem));
1088 init_value= initial;
1091 cl_memory_chip::~cl_memory_chip(void)
1098 cl_memory_chip::init(void)
1102 for (i= 0; i < size; i++)
1104 (init_value<0)?rand():(init_value));
1110 cl_memory_chip::get_slot(t_addr addr)
1115 return(&array[addr]);
1120 cl_memory_chip::get(t_addr addr)
1125 return(array[addr]);
1129 cl_memory_chip::set(t_addr addr, t_mem val)
1134 array[addr]= val & data_mask;
1138 cl_memory_chip::set_bit1(t_addr addr, t_mem bits)
1143 array[addr]|= (bits & data_mask);
1147 cl_memory_chip::set_bit0(t_addr addr, t_mem bits)
1152 array[addr]&= ((~bits) & data_mask);
1160 cl_address_decoder::cl_address_decoder(class cl_memory *as,
1161 class cl_memory *chip,
1162 t_addr asb, t_addr ase, t_addr cb)
1164 if (as->is_address_space())
1165 address_space= (class cl_address_space *)as;
1168 if (chip->is_chip())
1169 memchip= (class cl_memory_chip *)chip;
1175 activated= DD_FALSE;
1178 cl_address_decoder::~cl_address_decoder(void)
1182 for (a= as_begin; a <= as_end; a++)
1183 address_space->undecode_cell(a);
1187 cl_address_decoder::init(void)
1194 cl_address_decoder::activate(class cl_console *con)
1196 #define D if (con) con->debug
1197 D("Activation of an address decoder\n");
1200 D("Already activated\n");
1203 if (!address_space ||
1204 !address_space->is_address_space())
1206 D("No or non address space\n");
1210 !memchip->is_chip())
1212 D("No or non memory chip\n");
1215 if (as_begin > as_end)
1217 D("Wrong address area specification\n");
1220 if (chip_begin >= memchip->get_size())
1222 D("Wrong chip area specification\n");
1225 if (as_begin < address_space->start_address ||
1226 as_end >= address_space->start_address + address_space->get_size())
1228 D("Specified area is out of address space\n");
1231 if (as_end-as_begin > memchip->get_size()-chip_begin)
1233 D("Specified area is out of chip size\n");
1237 address_space->undecode_area(this, as_begin, as_end, con);
1240 for (asa= as_begin, ca= chip_begin;
1244 if (!address_space->decode_cell(asa, memchip, ca))
1246 D("Decoding 0x%06x->0x%06x failed\n", asa, ca);
1257 cl_address_decoder::fully_covered_by(t_addr begin, t_addr end)
1259 if (begin <= as_begin &&
1266 cl_address_decoder::is_in(t_addr begin, t_addr end)
1268 if (begin >= as_begin &&
1271 if (end >= as_begin &&
1278 cl_address_decoder::covers(t_addr begin, t_addr end)
1280 if (begin > as_begin &&
1287 /* Returns TRUE if shrunken decoder is unnecessary */
1290 cl_address_decoder::shrink_out_of(t_addr begin, t_addr end)
1301 address_space->undecode_cell(a);
1304 if (begin > as_begin)
1308 chip_begin+= (end-as_begin+1);
1311 if (as_end < as_begin)
1316 class cl_address_decoder *
1317 cl_address_decoder::split(t_addr begin, t_addr end)
1319 class cl_address_decoder *nd= 0;
1320 if (begin > as_begin)
1323 nd= new cl_address_decoder(address_space, memchip,
1324 end+1, as_end, chip_begin+(end-as_begin)+1);
1325 shrink_out_of(begin, as_end);
1327 else if (end < as_end)
1329 if (as_begin < begin)
1330 nd= new cl_address_decoder(address_space, memchip,
1331 as_begin, begin-1, chip_begin);
1332 shrink_out_of(end+1, as_end);
1341 * List of address decoders
1344 cl_decoder_list::cl_decoder_list(t_index alimit, t_index adelta, bool bychip):
1345 cl_sorted_list(alimit, adelta, "decoder list")
1347 Duplicates= DD_TRUE;
1352 cl_decoder_list::key_of(void *item)
1354 class cl_address_decoder *d= (class cl_address_decoder *)item;
1356 return(&(d->chip_begin));
1358 return(&(d->as_begin));
1362 cl_decoder_list::compare(void *key1, void *key2)
1364 t_addr k1= *((t_addr*)key1), k2= *((t_addr*)key2);
1374 * Errors in memory handling
1377 /* All of memory errors */
1378 ERROR_CLASS_DEF_PARENT_ON(err_error, mem, "memory",
1379 error_class_base, ERROR_ON);
1381 cl_error_mem::cl_error_mem(class cl_memory *amem, t_addr aaddr)
1385 classification= &error_mem_class;
1388 /* Invalid address in memory access */
1389 ERROR_CLASS_DEF_PARENT(err_error,
1390 mem_invalid_address,
1394 cl_error_mem_invalid_address::
1395 cl_error_mem_invalid_address(class cl_memory *amem, t_addr aaddr):
1396 cl_error_mem(amem, aaddr)
1398 classification= &error_mem_invalid_address_class;
1402 cl_error_mem_invalid_address::print(class cl_commander *c)
1404 c->dd_printf(get_type_name());
1405 c->dd_printf(": invalid address ", get_type_name());
1406 c->dd_printf(mem->addr_format, addr);
1407 c->dd_printf(" in memory ");
1408 c->dd_printf(mem->get_name());
1409 c->dd_printf(".\n");
1412 /* Non-decoded address space access */
1413 ERROR_CLASS_DEF_PARENT(err_error,
1418 cl_error_mem_non_decoded::
1419 cl_error_mem_non_decoded(class cl_memory *amem, t_addr aaddr):
1420 cl_error_mem(amem, aaddr)
1422 classification= &error_mem_non_decoded_class;
1426 cl_error_mem_non_decoded::print(class cl_commander *c)
1428 c->dd_printf(get_type_name());
1429 c->dd_printf(": access of non-decoded address ");
1430 c->dd_printf(mem->addr_format, addr);
1431 c->dd_printf(" in memory ");
1432 c->dd_printf(mem->get_name());
1433 c->dd_printf(".\n");