1 /*
2 * Simulator of microcontrollers (hw.cc)
3 *
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5 *
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7 *
8 */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <ctype.h>
31 #include <stdlib.h>
32 #include "i_string.h"
33
34 #include "stypes.h"
35 #include "globals.h"
36
37 #include "hwcl.h"
38
39
40 /*
41 *____________________________________________________________________________
42 */
43
cl_hw(class cl_uc * auc,enum hw_cath cath,int aid,const char * aid_string)44 cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, const char *aid_string):
45 cl_guiobj()
46 {
47 flags= HWF_INSIDE;
48 uc= auc;
49 cathegory= cath;
50 id= aid;
51 if (aid_string &&
52 *aid_string)
53 id_string= strdup(aid_string);
54 else
55 id_string= strdup("unknown hw element");
56 set_name(id_string);
57 char *s= (char*)malloc(strlen(get_name("hw"))+100);
58 sprintf(s, "partners of %s", get_name("hw"));
59 partners= new cl_list(2, 2, s);
60 sprintf(s, "watched cells of %s", get_name("hw"));
61 free(s);
62 cfg= 0;
63 io= 0;
64 }
65
~cl_hw(void)66 cl_hw::~cl_hw(void)
67 {
68 free((void*)id_string);
69 delete partners;
70 }
71
72 int
init(void)73 cl_hw::init(void)
74 {
75 chars n(id_string);
76 char s[100];
77 int i;
78
79 on= true;
80
81 snprintf(s, 99, "%d", id);
82 n+= '_';
83 n+= s;
84 n+= cchars("_cfg");
85
86 cfg= new cl_address_space(n, 0, cfg_size(), sizeof(t_mem)*8);
87 cfg->init();
88 cfg->hidden= true;
89 uc->address_spaces->add(cfg);
90
91 for (i= 0; i < cfg_size(); i++)
92 {
93 cfg->register_hw(i, this, false);
94 }
95
96 cache_run= -1;
97 cache_time= 0;
98 return 0;
99 }
100
101 void
new_hw_adding(class cl_hw * new_hw)102 cl_hw::new_hw_adding(class cl_hw *new_hw)
103 {
104 }
105
106 void
new_hw_added(class cl_hw * new_hw)107 cl_hw::new_hw_added(class cl_hw *new_hw)
108 {
109 int i;
110
111 for (i= 0; i < partners->count; i++)
112 {
113 class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
114 ph->refresh(new_hw);
115 }
116 }
117
118 class cl_hw *
make_partner(enum hw_cath cath,int id)119 cl_hw::make_partner(enum hw_cath cath, int id)
120 {
121 class cl_partner_hw *ph;
122 class cl_hw *hw;
123
124 ph= new cl_partner_hw(uc, cath, id);
125 partners->add(ph);
126 hw= ph->get_partner();
127 return(hw);
128 }
129
130 t_mem
read(class cl_memory_cell * cell)131 cl_hw::read(class cl_memory_cell *cell)
132 {
133 conf(cell, NULL);
134 return cell->get();
135 }
136
137 void
write(class cl_memory_cell * cell,t_mem * val)138 cl_hw::write(class cl_memory_cell *cell, t_mem *val)
139 {
140 conf(cell, val);
141 }
142
143 bool
conf(class cl_memory_cell * cell,t_mem * val)144 cl_hw::conf(class cl_memory_cell *cell, t_mem *val)
145 {
146 t_addr a;
147 if (cfg->is_owned(cell, &a))
148 {
149 conf_op(cell, a, val);
150 if (val)
151 cell->set(*val);
152 return true;
153 }
154 return false;
155 }
156
157 t_mem
conf_op(cl_memory_cell * cell,t_addr addr,t_mem * val)158 cl_hw::conf_op(cl_memory_cell *cell, t_addr addr, t_mem *val)
159 {
160 return cell->get();
161 }
162
163 void
cfg_set(t_addr addr,t_mem val)164 cl_hw::cfg_set(t_addr addr, t_mem val)
165 {
166 cfg->set(addr, val);
167 }
168
169 void
cfg_write(t_addr addr,t_mem val)170 cl_hw::cfg_write(t_addr addr, t_mem val)
171 {
172 cfg->write(addr, val);
173 }
174
175 t_mem
cfg_get(t_addr addr)176 cl_hw::cfg_get(t_addr addr)
177 {
178 return cfg->get(addr);
179 }
180
181 t_mem
cfg_read(t_addr addr)182 cl_hw::cfg_read(t_addr addr)
183 {
184 return cfg->read(addr);
185 }
186
187 char *
cfg_help(t_addr addr)188 cl_hw::cfg_help(t_addr addr)
189 {
190 return (char*)"N/A";
191 }
192
193 void
set_cmd(class cl_cmdline * cmdline,class cl_console_base * con)194 cl_hw::set_cmd(class cl_cmdline *cmdline, class cl_console_base *con)
195 {
196 con->dd_printf("Nothing to do\n");
197 }
198
199 class cl_memory_cell *
register_cell(class cl_address_space * mem,t_addr addr)200 cl_hw::register_cell(class cl_address_space *mem, t_addr addr)
201 {
202 if (mem)
203 mem->register_hw(addr, this, false);
204 else
205 printf("regcell JAJ no mem\n");
206 return mem->get_cell(addr);
207 }
208
209 class cl_memory_cell *
register_cell(class cl_memory_cell * cell)210 cl_hw::register_cell(class cl_memory_cell *cell)
211 {
212 if (cell)
213 {
214 cell->add_hw(this);
215 }
216 return cell;
217 }
218
219 void
unregister_cell(class cl_memory_cell * the_cell)220 cl_hw::unregister_cell(class cl_memory_cell *the_cell)
221 {
222 if (the_cell)
223 the_cell->remove_hw(this);
224 }
225
226
227 /*
228 * Simulating `cycles' number of machine cycle
229 */
230
231 int
tick(int cycles)232 cl_hw::tick(int cycles)
233 {
234 return(0);
235 }
236
237 void
inform_partners(enum hw_event he,void * params)238 cl_hw::inform_partners(enum hw_event he, void *params)
239 {
240 int i;
241
242 for (i= 0; i < partners->count; i++)
243 {
244 class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
245 ph->happen(this, he, params);
246 }
247 }
248
249 void
touch(void)250 cl_hw::touch(void)
251 {
252 refresh_display(false);
253 }
254
255 void
make_io()256 cl_hw::make_io()
257 {
258 if (!io)
259 {
260 io= new cl_hw_io(this);
261 io->init();
262 application->get_commander()->add_console(io);
263 }
264 }
265
266 void
new_io(class cl_f * f_in,class cl_f * f_out)267 cl_hw::new_io(class cl_f *f_in, class cl_f *f_out)
268 {
269 make_io();
270 if (!io)
271 return ;
272 io->tu_reset();
273 io->replace_files(true, f_in, f_out);
274 if (f_in)
275 {
276 f_in->interactive(NULL);
277 f_in->raw();
278 f_in->echo(NULL);
279 }
280 draw_display();
281 //application->get_commander()->update_active();
282 }
283
284 void
new_i(class cl_f * f_in)285 cl_hw::new_i(class cl_f *f_in)
286 {
287 make_io();
288 if (!io)
289 return ;
290 io->tu_reset();
291 io->replace_files(true, f_in, io->get_fout());
292 if (f_in)
293 {
294 f_in->interactive(NULL);
295 f_in->raw();
296 f_in->echo(NULL);
297 }
298 draw_display();
299 }
300
301 void
new_o(class cl_f * f_out)302 cl_hw::new_o(class cl_f *f_out)
303 {
304 make_io();
305 if (!io)
306 return ;
307 io->tu_reset();
308 io->replace_files(true, io->get_fin(), f_out);
309 draw_display();
310 }
311
312 class cl_hw_io *
get_io(void)313 cl_hw::get_io(void)
314 {
315 return io;
316 }
317
318 bool
proc_input(void)319 cl_hw::proc_input(void)
320 {
321 int c;
322
323 if (!io)
324 return false;
325
326 class cl_f *fin= io->get_fin();
327 class cl_f *fout= io->get_fout();
328
329 if (fin)
330 {
331 if (fin->eof())
332 {
333 if (fout &&
334 (fout->file_id == fin->file_id))
335 {
336 io->tu_reset();
337 delete fout;
338 io->replace_files(false, fin, 0);
339 }
340 delete fin;
341 io->replace_files(false, 0, 0);
342 return true;
343 }
344 fin->read(&c, 1);
345 return handle_input(c);
346 }
347 return false;
348 }
349
350 bool
handle_input(int c)351 cl_hw::handle_input(int c)
352 {
353 if (!io)
354 return false;
355
356 io->tu_go(1,3);
357 io->tu_cll();
358 switch (c)
359 {
360 case 's'-'a'+1: case 'r'-'a'+1: case 'g'-'a'+1:
361 uc->sim->change_run();
362 if (uc->sim->state & SIM_GO)
363 io->dd_printf("Simulation started.");
364 else
365 io->dd_printf("Simulation stopped.");
366 break;
367 case 't'-'a'+1:
368 uc->reset();
369 io->dd_printf("CPU reset.");
370 break;
371 case 'q'-'a'+1:
372 uc->sim->state|= SIM_QUIT;
373 io->dd_printf("Exit simulator.");
374 io->tu_reset();
375 break;
376 case 'o'-'a'+1:
377 io->dd_printf("Closing display.");
378 io->tu_reset();
379 io->tu_cls();
380 io->convert2console();
381 break;
382 case 'l'-'a'+1:
383 draw_display();
384 break;
385 case 'n'-'a'+1:
386 {
387 class cl_hw *h= next_displayer();
388 if (!h)
389 io->dd_printf("No other displayer.");
390 else
391 {
392 io->tu_reset();
393 io->tu_cls();
394 io->pass2hw(h);
395 }
396 break;
397 }
398 default:
399 return false;
400 break;
401 }
402 return true;
403 }
404
405 void
refresh_display(bool force)406 cl_hw::refresh_display(bool force)
407 {
408 if (!io)
409 return ;
410 int n= uc->sim->state & SIM_GO;
411 if ((n != cache_run) ||
412 force)
413 {
414 io->tu_go(66,1);
415 if (n)
416 io->dd_cprintf("ui_run" , "%s", "Run ");
417 else
418 io->dd_cprintf("ui_stop", "%s", "Stop");
419 cache_run= n;
420 }
421 unsigned int t= (unsigned int)(uc->get_rtime()) * 500;
422 if ((t != cache_time) ||
423 force)
424 {
425 io->tu_go(28,2);
426 io->dd_cprintf("ui_time", "%u ms", t);
427 if (t < cache_time)
428 io->dd_printf(" ");
429 cache_time= t;
430 }
431 }
432
433 void
draw_display(void)434 cl_hw::draw_display(void)
435 {
436 if (!io)
437 return ;
438 io->tu_go(1, 1);
439 io->dd_cprintf("ui_mkey", "[^s] ");
440 io->dd_cprintf("ui_mitem", "Start/stop ");
441 io->dd_cprintf("ui_mkey", "[^t] ");
442 io->dd_cprintf("ui_mitem", "reseT ");
443 io->dd_cprintf("ui_mkey", "[^q] ");
444 io->dd_cprintf("ui_mitem", "Quit ");
445 io->dd_cprintf("ui_mkey", "[^o] ");
446 io->dd_cprintf("ui_mitem", "clOse ");
447 io->dd_cprintf("ui_mkey", "[^l] ");
448 io->dd_cprintf("ui_mitem", "redraw\n");
449 io->dd_cprintf("ui_mkey", "[^n] ");
450 io->dd_cprintf("ui_mitem", "chaNge display ");
451 io->dd_cprintf("ui_label", "Time: ");
452 io->tu_go(66,2);
453 chars s("", "%s[%d]", id_string, id);
454 io->dd_cprintf("ui_title", "%-13s", (char*)s);
455 }
456
457 class cl_hw *
next_displayer(void)458 cl_hw::next_displayer(void)
459 {
460 if (!uc)
461 return NULL;
462 return uc->hws->next_displayer(this);
463 }
464
465
466 void
print_info(class cl_console_base * con)467 cl_hw::print_info(class cl_console_base *con)
468 {
469 con->dd_printf("%s[%d]\n", id_string, id);
470 print_cfg_info(con);
471 }
472
473 void
print_cfg_info(class cl_console_base * con)474 cl_hw::print_cfg_info(class cl_console_base *con)
475 {
476 t_mem v;
477 t_addr a, s, e;
478 con->dd_printf("Configuration memory of %s\n", get_name());
479 if (cfg)
480 {
481 s= cfg->get_start_address();
482 e= s + cfg->get_size();
483 for (a= s; a <= e; a++)
484 {
485 v= cfg->read(a);
486 con->dd_cprintf("dump_address", "0x%02x ", AU(a));
487 con->dd_cprintf("dump_number", "%08x ",v);
488 if ((v < 128) &&
489 isprint((int)v))
490 con->dd_cprintf("dump_char", "%c", v);
491 else
492 con->dd_cprintf("dump_char", ".");
493 con->dd_printf(" %s\n", cfg_help(a));
494 }
495 }
496 }
497
498 /*
499 * List of hw
500 */
501
502 t_index
add(void * item)503 cl_hws::add(void *item)
504 {
505 int i;
506 t_index res;
507
508 // pre-add
509 for (i= 0; i < count; i++)
510 {
511 class cl_hw *hw= (class cl_hw *)(at(i));
512 hw->new_hw_adding((class cl_hw *)item);
513 }
514 // add
515 res= cl_list::add(item);
516 // post-add
517 for (i= 0; i < count; i++)
518 {
519 class cl_hw *hw= (class cl_hw *)(at(i));
520 hw->new_hw_added((class cl_hw *)item);
521 }
522 ((class cl_hw *)item)->added_to_uc();
523 return(res);
524 }
525
526 class cl_hw *
next_displayer(class cl_hw * hw)527 cl_hws::next_displayer(class cl_hw *hw)
528 {
529 int i, j;
530 cl_hw_io *io;
531 cl_f *fi, *fo;
532
533 if (!index_of(hw, &i))
534 return NULL;
535
536 for (j= i+1; j < count; j++)
537 {
538 class cl_hw *h= (class cl_hw *)(at(j));
539 h->make_io();
540 if ((io= h->get_io()))
541 {
542 fi= io->get_fin();
543 fo= io->get_fout();
544 if (!fi &&
545 !fo)
546 return h;
547 }
548 }
549 for (j= 0; j < i; j++)
550 {
551 class cl_hw *h= (class cl_hw *)(at(j));
552 h->make_io();
553 if ((io= h->get_io()))
554 {
555 fi= io->get_fin();
556 fo= io->get_fout();
557 if (!fi &&
558 !fo)
559 return h;
560 }
561 }
562 return NULL;
563 }
564
565
566 /*
567 *____________________________________________________________________________
568 */
569
cl_partner_hw(class cl_uc * auc,enum hw_cath cath,int aid)570 cl_partner_hw::cl_partner_hw(class cl_uc *auc, enum hw_cath cath, int aid):
571 cl_base()
572 {
573 uc= auc;
574 cathegory= cath;
575 id= aid;
576 partner= uc->get_hw(cathegory, id, 0);
577 }
578
579 class cl_hw *
get_partner(void)580 cl_partner_hw::get_partner(void)
581 {
582 return(partner);
583 }
584
585 void
refresh(void)586 cl_partner_hw::refresh(void)
587 {
588 class cl_hw *hw= uc->get_hw(cathegory, id, 0);
589
590 if (!hw)
591 return;
592 if (partner)
593 {
594 // partner is already set
595 if (partner != hw)
596 {
597 // partner changed?
598 partner= hw;
599 }
600 else
601 partner= hw;
602 }
603 partner= hw;
604 }
605
606 void
refresh(class cl_hw * new_hw)607 cl_partner_hw::refresh(class cl_hw *new_hw)
608 {
609 if (!new_hw)
610 return;
611 if (cathegory == new_hw->cathegory &&
612 id == new_hw->id)
613 {
614 if (partner)
615 {
616 // partner changed?
617 partner= new_hw;
618 }
619 else
620 partner= new_hw;
621 }
622 }
623
624 void
happen(class cl_hw * where,enum hw_event he,void * params)625 cl_partner_hw::happen(class cl_hw *where, enum hw_event he, void *params)
626 {
627 if (partner)
628 partner->happen(where, he, params);
629 }
630
631
632 /*
633 *____________________________________________________________________________
634 */
635
cl_hw_io(class cl_hw * ihw)636 cl_hw_io::cl_hw_io(class cl_hw *ihw):
637 cl_console()
638 {
639 hw= ihw;
640 set_name(chars("", "%s[%d]", ihw->id_string, ihw->id));
641 }
642
643 int
init(void)644 cl_hw_io::init(void)
645 {
646 set_flag(CONS_NOWELCOME, true);
647 return 0;
648 }
649
650 int
proc_input(class cl_cmdset * cmdset)651 cl_hw_io::proc_input(class cl_cmdset *cmdset)
652 {
653 if (hw)
654 hw->proc_input();
655 else
656 {
657 int c;
658 fin->read(&c, 1);
659 dd_printf("Unhandled hwio command: %c %d 0x%02x\n", isprint(c)?c:'?', c, c);
660 }
661 return 0;
662 }
663
664
665 void
convert2console(void)666 cl_hw_io::convert2console(void)
667 {
668 if (fin &&
669 fout)
670 {
671 class cl_console *con= new cl_console(fin, fout, application);
672 con->init();
673 application->get_commander()->add_console(con);
674 }
675 drop_files();
676 }
677
678 void
pass2hw(class cl_hw * new_hw)679 cl_hw_io::pass2hw(class cl_hw *new_hw)
680 {
681 if (new_hw)
682 new_hw->new_io(fin, fout);
683 drop_files();
684 }
685
686
687 /* End of hw.cc */
688