Imported Upstream version 2.9.0
[debian/cc1111] / sim / ucsim / sim.src / hw.cc
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 <stdlib.h>
31 #include "i_string.h"
32
33 #include "stypes.h"
34 #include "hwcl.h"
35
36
37 /*
38  *____________________________________________________________________________
39  */
40
41 cl_watched_cell::cl_watched_cell(class cl_address_space *amem, t_addr aaddr,
42                                  class cl_memory_cell **astore,
43                                  enum what_to_do_on_cell_change awtd)
44 {
45   mem= amem;
46   addr= aaddr;
47   store= astore;
48   wtd= awtd;
49   if (mem)
50     {
51       cell= mem->get_cell(addr);
52       if (store)
53         *store= cell;
54     }
55 }
56
57 void
58 cl_watched_cell::mem_cell_changed(class cl_address_space *amem, t_addr aaddr,
59                                   class cl_hw *hw)
60 {
61   if (mem &&
62       mem == amem &&
63       addr == aaddr)
64     {
65       cell= mem->get_cell(addr);
66       if (store &&
67           (wtd & WTD_RESTORE))
68         *store= cell;
69       if (wtd & WTD_WRITE)
70         {
71           t_mem d= cell->get();
72           hw->write(cell, &d);
73         }
74     }
75 }
76
77 void
78 cl_watched_cell::address_space_added(class cl_address_space *amem,
79                                      class cl_hw *hw)
80 {
81 }
82
83 void
84 cl_used_cell::mem_cell_changed(class cl_address_space *amem, t_addr aaddr, 
85 class cl_hw *hw)
86 {
87   if (mem &&
88       mem == amem &&
89       addr == aaddr)
90     {
91       cell= mem->get_cell(addr);
92       if (store &&
93           (wtd & WTD_RESTORE))
94         *store= cell;
95       if (wtd & WTD_WRITE)
96         {
97           t_mem d= cell->get();
98           hw->write(cell, &d);
99         }
100     }
101 }
102
103 void
104 cl_used_cell::address_space_added(class cl_address_space *amem,
105                                   class cl_hw *hw)
106 {
107 }
108
109
110 /*
111  *____________________________________________________________________________
112  */
113
114 cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, const char *aid_string):
115   cl_guiobj()
116 {
117   flags= HWF_INSIDE;
118   uc= auc;
119   cathegory= cath;
120   id= aid;
121   if (aid_string &&
122       *aid_string)
123     id_string= strdup(aid_string);
124   else
125     id_string= strdup("unknown hw element");
126   char *s= (char*)malloc(strlen(get_name("hw"))+100);
127   sprintf(s, "partners of %s", get_name("hw"));
128   partners= new cl_list(2, 2, s);
129   sprintf(s, "watched cells of %s", get_name("hw"));
130   watched_cells= new cl_list(2, 2, s);
131   free(s);
132 }
133
134 cl_hw::~cl_hw(void)
135 {
136   free(id_string);
137   //hws_to_inform->disconn_all();
138   delete partners;
139   delete watched_cells;
140 }
141
142
143 void
144 cl_hw::new_hw_adding(class cl_hw *new_hw)
145 {
146 }
147
148 void
149 cl_hw::new_hw_added(class cl_hw *new_hw)
150 {
151   int i;
152
153   for (i= 0; i < partners->count; i++)
154     {
155       class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
156       ph->refresh(new_hw);
157     }
158 }
159
160 class cl_hw *
161 cl_hw::make_partner(enum hw_cath cath, int id)
162 {
163   class cl_partner_hw *ph;
164   class cl_hw *hw;
165
166   ph= new cl_partner_hw(uc, cath, id);
167   partners->add(ph);
168   hw= ph->get_partner();
169   return(hw);
170 }
171
172
173 /*
174  * Callback functions for changing memory locations
175  */
176
177 /*t_mem
178 cl_hw::read(class cl_m *mem, t_addr addr)
179 {
180   // Simply return the value
181   return(mem->get(addr));
182 }*/
183
184 /*void
185 cl_hw::write(class cl_m *mem, t_addr addr, t_mem *val)
186 {
187   // Do not change *val by default
188 }*/
189
190 void
191 cl_hw::set_cmd(class cl_cmdline *cmdline, class cl_console_base *con)
192 {
193   con->dd_printf("Nothing to do\n");
194 }
195
196 class cl_memory_cell *
197 cl_hw::register_cell(class cl_address_space *mem, t_addr addr,
198                      class cl_memory_cell **store,
199                      enum what_to_do_on_cell_change awtd)
200 {
201   class cl_watched_cell *wc;
202   class cl_memory_cell *cell;
203
204   if (mem)
205     mem->register_hw(addr, this, (int*)0, DD_FALSE);
206   else
207     printf("regcell JAJ no mem\n");
208   wc= new cl_watched_cell(mem, addr, &cell, awtd);
209   if (store)
210     *store= cell;
211   watched_cells->add(wc);
212   // announce
213   //uc->sim->mem_cell_changed(mem, addr);
214   return(cell);
215 }
216
217 class cl_memory_cell *
218 cl_hw::use_cell(class cl_address_space *mem, t_addr addr,
219                 class cl_memory_cell **store,
220                 enum what_to_do_on_cell_change awtd)
221 {
222   class cl_watched_cell *wc;
223   class cl_memory_cell *cell;
224
225   wc= new cl_used_cell(mem, addr, &cell, awtd);
226   if (store)
227     *store= cell;
228   watched_cells->add(wc);
229   return(cell);
230 }
231
232 void
233 cl_hw::mem_cell_changed(class cl_address_space *mem, t_addr addr)
234 {
235   int i;
236
237   for (i= 0; i < watched_cells->count; i++)
238     {
239       class cl_watched_cell *wc=
240         (class cl_watched_cell *)(watched_cells->at(i));
241       wc->mem_cell_changed(mem, addr, this);
242     }
243 }
244
245 void
246 cl_hw::address_space_added(class cl_address_space *as)
247 {
248   int i;
249
250   for (i= 0; i < watched_cells->count; i++)
251     {
252       class cl_watched_cell *wc=
253         dynamic_cast<class cl_watched_cell *>(watched_cells->object_at(i));
254       wc->address_space_added(as, this);
255     }
256 }
257
258
259 /*
260  * Simulating `cycles' number of machine cycle
261  */
262
263 int
264 cl_hw::tick(int cycles)
265 {
266   return(0);
267 }
268
269 void
270 cl_hw::inform_partners(enum hw_event he, void *params)
271 {
272   int i;
273
274   for (i= 0; i < partners->count; i++)
275     {
276       class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
277       ph->happen(this, he, params);
278     }
279 }
280
281
282 void
283 cl_hw::print_info(class cl_console_base *con)
284 {
285   con->dd_printf("%s[%d]\n", id_string, id);
286 }
287
288
289 t_index
290 cl_hws::add(void *item)
291 {
292   int i;
293   t_index res;
294
295   // pre-add
296   for (i= 0; i < count; i++)
297     {
298       class cl_hw *hw= (class cl_hw *)(at(i));
299       hw->new_hw_adding((class cl_hw *)item);
300     }
301   // add
302   res= cl_list::add(item);
303   // post-add
304   for (i= 0; i < count; i++)
305     {
306       class cl_hw *hw= (class cl_hw *)(at(i));
307       hw->new_hw_added((class cl_hw *)item);
308     }
309   ((class cl_hw *)item)->added_to_uc();
310   return(res);
311 }
312
313
314 void
315 cl_hws::mem_cell_changed(class cl_address_space *mem, t_addr addr)
316 {
317   int i;
318   
319   for (i= 0; i < count; i++)
320     {
321       class cl_hw *hw= (class cl_hw *)(at(i));
322       hw->mem_cell_changed(mem, addr);
323     }
324 }
325
326 void
327 cl_hws::address_space_added(class cl_address_space *mem)
328 {
329   int i;
330   
331   for (i= 0; i < count; i++)
332     {
333       class cl_hw *hw= (class cl_hw *)(at(i));
334       hw->address_space_added(mem);
335     }
336 }
337
338
339 /*
340  *____________________________________________________________________________
341  */
342
343 cl_partner_hw::cl_partner_hw(class cl_uc *auc, enum hw_cath cath, int aid):
344   cl_base()
345 {
346   uc= auc;
347   cathegory= cath;
348   id= aid;
349   partner= uc->get_hw(cathegory, id, 0);
350 }
351
352 class cl_hw *
353 cl_partner_hw::get_partner(void)
354 {
355   return(partner);
356 }
357
358 void
359 cl_partner_hw::refresh(void)
360 {
361   class cl_hw *hw= uc->get_hw(cathegory, id, 0);
362
363   if (!hw)
364     return;
365   if (partner)
366     {
367       // partner is already set
368       if (partner != hw)
369         {
370           // partner changed?
371           partner= hw;
372         }
373       else
374         partner= hw;
375     }
376   partner= hw;
377 }
378
379 void
380 cl_partner_hw::refresh(class cl_hw *new_hw)
381 {
382   if (!new_hw)
383     return;
384   if (cathegory == new_hw->cathegory &&
385       id == new_hw->id)
386     {
387       if (partner)
388         {
389           // partner changed?
390           partner= new_hw;
391         }
392       else
393         partner= new_hw;
394     }
395 }
396
397 void
398 cl_partner_hw::happen(class cl_hw *where, enum hw_event he, void *params)
399 {
400   if (partner)
401     partner->happen(where, he, params);
402 }
403
404
405 /* End of hw.cc */