📄 mem.cc
字号:
t_addr astart, t_addr asize, int awidth): cl_memory(id, asize, awidth){ start_address= astart; decoders= new cl_decoder_list(2, 2, DD_FALSE); cells= (class cl_memory_cell **)calloc(size, sizeof(class cl_memory_cell*)); dummy= new cl_dummy_cell();}cl_address_space::~cl_address_space(void){ delete decoders; int i; for (i= 0; i < size; i++) if (cells[i]) delete cells[i]; delete dummy;} t_memcl_address_space::read(t_addr addr){ return get_cell(addr)->read();}t_memcl_address_space::read(t_addr addr, enum hw_cath skip){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return dummy->read(); } return cell->read(skip);}t_memcl_address_space::get(t_addr addr){ return get_cell(addr)->get();}t_memcl_address_space::write(t_addr addr, t_mem val){ return get_cell(addr)->write(val);}voidcl_address_space::set(t_addr addr, t_mem val){ get_cell(addr)->set(val);}t_memcl_address_space::wadd(t_addr addr, long what){ return get_cell(addr)->wadd(what);}/* Set or clear bits, without callbacks */voidcl_address_space::set_bit1(t_addr addr, t_mem bits){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return; } cell->set_bit1(bits);}voidcl_address_space::set_bit0(t_addr addr, t_mem bits){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return; } cell->set_bit0(bits);}class cl_address_decoder *cl_address_space::get_decoder(t_addr addr){ int i; for (i= 0; i < decoders->count; i++) { class cl_address_decoder *d= dynamic_cast<class cl_address_decoder *>(decoders->object_at(i)); if (!d) continue; if (d->covers(addr, addr)) { return d; } } return NULL;}class cl_memory_cell *cl_address_space::get_cell(t_addr addr){ t_addr idx= addr-start_address; if (idx >= size || addr < start_address) { err_inv_addr(addr); return(dummy); } if (cells[idx] == NULL) { cells[idx]= new cl_memory_cell(); cells[idx]->init(); class cl_address_decoder *decoder; decoder = get_decoder(addr); if (decoder && decoder->activated) { decode_cell(addr, decoder->memchip, addr - decoder->as_begin + decoder->chip_begin); } } return(cells[idx]);}intcl_address_space::get_cell_flag(t_addr addr){ return get_cell(addr)->get_flags();}boolcl_address_space::get_cell_flag(t_addr addr, enum cell_flag flag){ return get_cell(addr)->get_flag(flag);}voidcl_address_space::set_cell_flag(t_addr addr, bool set_to, enum cell_flag flag){ get_cell(addr)->set_flag(flag, set_to);}boolcl_address_space::decode_cell(t_addr addr, class cl_memory_chip *chip, t_addr chipaddr){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return(DD_FALSE); } if (!cell->get_flag(CELL_NON_DECODED)) { // un-decode first! cell->un_decode(); } cell->decode(chip, chipaddr); return(!cell->get_flag(CELL_NON_DECODED));}voidcl_address_space::undecode_cell(t_addr addr){ t_addr idx= addr-start_address; if (idx >= size || addr < start_address) { err_inv_addr(addr); return; } if (cells[idx] == NULL) { return; } cells[idx]->un_decode();}voidcl_address_space::undecode_area(class cl_address_decoder *skip, t_addr begin, t_addr end,class cl_console *con){#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++) { class cl_address_decoder *d= dynamic_cast<class cl_address_decoder *>(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); } } }#undef D}class cl_memory_cell *cl_address_space::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return(NULL); } 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);}voidcl_address_space::set_brk(t_addr addr, class cl_brk *brk){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return; } class cl_memory_operator *op; switch (brk->get_event()) { 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; } if (op) cell->append_operator(op);}voidcl_address_space::del_brk(t_addr addr, class cl_brk *brk){ cl_memory_cell *cell = get_cell(addr); if (cell == dummy) { return; } switch (brk->get_event()) { 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; }}/* * List of address spaces */cl_address_space_list::cl_address_space_list(class cl_uc *the_uc): cl_list(2, 2, "address spaces"){ uc= the_uc;}t_indexcl_address_space_list::add(class cl_address_space *mem){ mem->set_uc(uc); t_index ret= cl_list::add(mem); if (uc) { class cl_event_address_space_added e(mem); uc->handle_event(e); } return(ret);}/* * Memory chip */cl_memory_chip::cl_memory_chip(char *id, int asize, int awidth, int initial): cl_memory(id, asize, awidth){ array= (t_mem *)malloc(size * sizeof(t_mem)); init_value= initial;}cl_memory_chip::~cl_memory_chip(void){ if (array) free(array);}intcl_memory_chip::init(void){ cl_memory::init(); int i; for (i= 0; i < size; i++) set(i, (init_value<0)?rand():(init_value)); return(0);}t_mem *cl_memory_chip::get_slot(t_addr addr){ if (!array || size <= addr) return(0); return(&array[addr]);}t_memcl_memory_chip::get(t_addr addr){ if (!array || size <= addr) return(0); return(array[addr]);}voidcl_memory_chip::set(t_addr addr, t_mem val){ if (!array || size <= addr) return; array[addr]= val & data_mask;}voidcl_memory_chip::set_bit1(t_addr addr, t_mem bits){ if (!array || size <= addr) return; array[addr]|= (bits & data_mask);}voidcl_memory_chip::set_bit0(t_addr addr, t_mem bits){ if (!array || size <= addr) return; array[addr]&= ((~bits) & data_mask);}/* * 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 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;}cl_address_decoder::~cl_address_decoder(void){ t_addr a; if (address_space) for (a= as_begin; a <= as_end; a++) address_space->undecode_cell(a);}intcl_address_decoder::init(void){ return(0);}boolcl_address_decoder::activate(class cl_console *con){#define D if (con) con->debug D("Activation of an address decoder\n"); if (activated) { D("Already activated\n"); return(DD_FALSE); } if (!address_space || !address_space->is_address_space()) { D("No or non address space\n"); return(DD_FALSE); } if (!memchip || !memchip->is_chip()) { D("No or non memory chip\n"); return(DD_FALSE); } if (as_begin > as_end) { D("Wrong address area specification\n"); return(DD_FALSE); } if (chip_begin >= memchip->get_size()) { D("Wrong chip area specification\n"); return(DD_FALSE); } if (as_begin < address_space->start_address || as_end >= address_space->start_address + address_space->get_size()) { D("Specified area is out of address space\n"); return(DD_FALSE); } if (as_end-as_begin > memchip->get_size()-chip_begin) { D("Specified area is out of chip size\n"); return(DD_FALSE); } address_space->undecode_area(this, as_begin, as_end, con); activated= DD_TRUE;#undef D return(activated);}boolcl_address_decoder::fully_covered_by(t_addr begin, t_addr end){ if (begin <= as_begin && end >= as_end) return(DD_TRUE); return(DD_FALSE);}boolcl_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);}boolcl_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 */boolcl_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) { address_space->undecode_cell(a); a++; } if (begin > as_begin) as_end= begin-1; if (as_end > end) { chip_begin+= (end-as_begin+1); as_begin= end+1; } if (as_end < as_begin) return(DD_TRUE); return(DD_FALSE);}class cl_address_decoder *cl_address_decoder::split(t_addr begin, t_addr end){ class cl_address_decoder *nd= 0; if (begin > as_begin) { 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 if (end < as_end) { 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); } if (nd) nd->init(); return(nd);}/* * List of address decoders */cl_decoder_list::cl_decoder_list(t_index alimit, t_index adelta, bool bychip): cl_sorted_list(alimit, adelta, "decoder list"){ Duplicates= DD_TRUE; by_chip= bychip;}void *cl_decoder_list::key_of(void *item){ class cl_address_decoder *d= (class cl_address_decoder *)item; if (by_chip) return(&(d->chip_begin)); else return(&(d->as_begin));}intcl_decoder_list::compare(void *key1, void *key2){ t_addr k1= *((t_addr*)key1), k2= *((t_addr*)key2); if (k1 == k2) return(0); else if (k1 > k2) return(1); return(-1);}/* * Errors in memory handling *//* All of memory errors */cl_error_mem::cl_error_mem(class cl_memory *amem, t_addr aaddr){ mem= amem; addr= aaddr; classification= mem_error_registry.find("memory");}/* Invalid address in memory access */cl_error_mem_invalid_address::cl_error_mem_invalid_address(class cl_memory *amem, t_addr aaddr): cl_error_mem(amem, aaddr){ classification= mem_error_registry.find("invalid_address");}voidcl_error_mem_invalid_address::print(class cl_commander *c){ FILE *f= c->get_out(); cmd_fprintf(f, "%s: invalid address ", get_type_name()); cmd_fprintf(f, mem->addr_format, addr); cmd_fprintf(f, " in memory %s.\n", mem->get_name());}/* Non-decoded address space access */cl_error_mem_non_decoded::cl_error_mem_non_decoded(class cl_memory *amem, t_addr aaddr): cl_error_mem(amem, aaddr){ classification= mem_error_registry.find("non_decoded");}voidcl_error_mem_non_decoded::print(class cl_commander *c){ FILE *f= c->get_out(); cmd_fprintf(f, "%s: access of non-decoded address ", get_type_name()); cmd_fprintf(f, mem->addr_format, addr); cmd_fprintf(f, " in memory %s.\n", mem->get_name());}cl_mem_error_registry::cl_mem_error_registry(void){ class cl_error_class *prev = mem_error_registry.find("non-classified"); prev = register_error(new cl_error_class(err_error, "memory", prev, ERROR_OFF)); prev = register_error(new cl_error_class(err_error, "invalid_address", prev)); prev = register_error(new cl_error_class(err_error, "non_decoded", prev));}/* End of mem.cc */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -