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