167c1cad9527210d3dae1604d639d9bfc851fe06
[fw/sdcc] / 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_mem *amem, t_addr aaddr,
42                                  class cl_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_mem *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_used_cell::mem_cell_changed(class cl_mem *amem, t_addr aaddr, 
79 class cl_hw *hw)
80 {
81   if (mem &&
82       mem == amem &&
83       addr == aaddr)
84     {
85       cell= mem->get_cell(addr);
86       if (store &&
87           (wtd & WTD_RESTORE))
88         *store= cell;
89       if (wtd & WTD_WRITE)
90         {
91           t_mem d= cell->get();
92           hw->write(cell, &d);
93         }
94     }
95 }*/
96
97
98 /*
99  *____________________________________________________________________________
100  */
101
102 cl_hw::cl_hw(class cl_uc *auc, enum hw_cath cath, int aid, char *aid_string):
103   cl_guiobj()
104 {
105   flags= HWF_INSIDE;
106   uc= auc;
107   cathegory= cath;
108   id= aid;
109   if (aid_string &&
110       *aid_string)
111     id_string= strdup(aid_string);
112   else
113     id_string= strdup("unknown hw element");
114   partners= new cl_list(2, 2);
115   watched_cells= new cl_list(2, 2);
116 }
117
118 cl_hw::~cl_hw(void)
119 {
120   free(id_string);
121   //hws_to_inform->disconn_all();
122   delete partners;
123   delete watched_cells;
124 }
125
126
127 void
128 cl_hw::new_hw_adding(class cl_hw *new_hw)
129 {
130 }
131
132 void
133 cl_hw::new_hw_added(class cl_hw *new_hw)
134 {
135   int i;
136
137   for (i= 0; i < partners->count; i++)
138     {
139       class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
140       ph->refresh(new_hw);
141     }
142 }
143
144 class cl_hw *
145 cl_hw::make_partner(enum hw_cath cath, int id)
146 {
147   class cl_partner_hw *ph;
148   class cl_hw *hw;
149
150   ph= new cl_partner_hw(uc, cath, id);
151   partners->add(ph);
152   hw= ph->get_partner();
153   return(hw);
154 }
155
156
157 /*
158  * Callback functions for changing memory locations
159  */
160
161 /*t_mem
162 cl_hw::read(class cl_mem *mem, t_addr addr)
163 {
164   // Simply return the value
165   return(mem->get(addr));
166 }*/
167
168 /*void
169 cl_hw::write(class cl_mem *mem, t_addr addr, t_mem *val)
170 {
171   // Do not change *val by default
172 }*/
173
174
175 class cl_cell *
176 cl_hw::register_cell(class cl_mem *mem, t_addr addr, class cl_cell **store,
177                      enum what_to_do_on_cell_change awtd)
178 {
179   class cl_watched_cell *wc;
180   class cl_cell *cell;
181
182   if (mem)
183     mem->register_hw(addr, this, (int*)0, DD_FALSE);
184   wc= new cl_watched_cell(mem, addr, &cell, awtd);
185   if (store)
186     *store= cell;
187   watched_cells->add(wc);
188   // announce
189   uc->sim->mem_cell_changed(mem, addr);
190   return(cell);
191 }
192
193 class cl_cell *
194 cl_hw::use_cell(class cl_mem *mem, t_addr addr, class cl_cell **store,
195                 enum what_to_do_on_cell_change awtd)
196 {
197   class cl_watched_cell *wc;
198   class cl_cell *cell;
199
200   wc= new cl_used_cell(mem, addr, &cell, awtd);
201   if (store)
202     *store= cell;
203   watched_cells->add(wc);
204   return(cell);
205 }
206
207 void
208 cl_hw::mem_cell_changed(class cl_mem *mem, t_addr addr)
209 {
210   int i;
211
212   for (i= 0; i < watched_cells->count; i++)
213     {
214       class cl_watched_cell *wc=
215         (class cl_watched_cell *)(watched_cells->at(i));
216       wc->mem_cell_changed(mem, addr, this);
217     }
218 }
219
220
221 /*
222  * Simulating `cycles' number of machine cycle
223  */
224
225 int
226 cl_hw::tick(int cycles)
227 {
228   return(0);
229 }
230
231 void
232 cl_hw::inform_partners(enum hw_event he, void *params)
233 {
234   int i;
235
236   for (i= 0; i < partners->count; i++)
237     {
238       class cl_partner_hw *ph= (class cl_partner_hw *)(partners->at(i));
239       ph->happen(this, he, params);
240     }
241 }
242
243
244 void
245 cl_hw::print_info(class cl_console *con)
246 {
247   con->dd_printf("%s[%d]\n", id_string, id);
248 }
249
250
251 t_index
252 cl_hws::add(void *item)
253 {
254   int i;
255   t_index res;
256
257   // pre-add
258   for (i= 0; i < count; i++)
259     {
260       class cl_hw *hw= (class cl_hw *)(at(i));
261       hw->new_hw_adding((class cl_hw *)item);
262     }
263   // add
264   res= cl_list::add(item);
265   // post-add
266   for (i= 0; i < count; i++)
267     {
268       class cl_hw *hw= (class cl_hw *)(at(i));
269       hw->new_hw_added((class cl_hw *)item);
270     }
271   ((class cl_hw *)item)->added_to_uc();
272   return(res);
273 }
274
275
276 void
277 cl_hws::mem_cell_changed(class cl_mem *mem, t_addr addr)
278 {
279   int i;
280   
281   for (i= 0; i < count; i++)
282     {
283       class cl_hw *hw= (class cl_hw *)(at(i));
284       hw->mem_cell_changed(mem, addr);
285     }
286 }
287
288
289 /*
290  *____________________________________________________________________________
291  */
292
293 cl_partner_hw::cl_partner_hw(class cl_uc *auc, enum hw_cath cath, int aid):
294   cl_base()
295 {
296   uc= auc;
297   cathegory= cath;
298   id= aid;
299   partner= uc->get_hw(cathegory, id, 0);
300 }
301
302 class cl_hw *
303 cl_partner_hw::get_partner(void)
304 {
305   return(partner);
306 }
307
308 void
309 cl_partner_hw::refresh(void)
310 {
311   class cl_hw *hw= uc->get_hw(cathegory, id, 0);
312
313   if (!hw)
314     return;
315   if (partner)
316     {
317       // partner is already set
318       if (partner != hw)
319         {
320           // partner changed?
321           partner= hw;
322         }
323       else
324         partner= hw;
325     }
326   partner= hw;
327 }
328
329 void
330 cl_partner_hw::refresh(class cl_hw *new_hw)
331 {
332   if (!new_hw)
333     return;
334   if (cathegory == new_hw->cathegory &&
335       id == new_hw->id)
336     {
337       if (partner)
338         {
339           // partner changed?
340           partner= new_hw;
341         }
342       else
343         partner= new_hw;
344     }
345 }
346
347 void
348 cl_partner_hw::happen(class cl_hw *where, enum hw_event he, void *params)
349 {
350   if (partner)
351     partner->happen(where, he, params);
352 }
353
354
355 /* End of hw.cc */