1 /*
2  * Simulator of microcontrollers (cmd.src/cmdmem.cc)
3  *
4  * Copyright (C) 2001,01 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 // prj
29 #include "globals.h"
30 #include "utils.h"
31 
32 // sim
33 #include "simcl.h"
34 
35 // local
36 #include "cmd_memcl.h"
37 
38 
39 void
set_memory_help(class cl_cmd * cmd)40 set_memory_help(class cl_cmd *cmd)
41 {
42   cmd->set_help("memory subcommand",
43 		"Manage memory chips and address spaces",
44 		"Long of memory");
45 }
46 
47 void
set_memory_create_help(class cl_cmd * cmd)48 set_memory_create_help(class cl_cmd *cmd)
49 {
50   cmd->set_help("memory create subcommand",
51 		"Set of commands to create memory objects",
52 		"Long of memory create");
53 }
54 
55 /*
56  * Command: memory create chip
57  *----------------------------------------------------------------------------
58  */
59 
60 //int
61 //cl_conf_addmem_cmd::do_work(class cl_sim *sim,
62 //			    class cl_cmdline *cmdline, class cl_console *con)
COMMAND_DO_WORK_UC(cl_memory_create_chip_cmd)63 COMMAND_DO_WORK_UC(cl_memory_create_chip_cmd)
64 {
65   class cl_cmd_arg *params[4]= { cmdline->param(0),
66 				 cmdline->param(1),
67 				 cmdline->param(2),
68 				 cmdline->param(3) };
69   char *memid= NULL;
70   int size= -1;
71   int width= 8;
72 
73   if (cmdline->syntax_match(uc, STRING NUMBER)) {
74     memid= params[0]->value.string.string;
75     size= params[1]->value.number;
76   }
77   else if (cmdline->syntax_match(uc, STRING NUMBER NUMBER)) {
78     memid= params[0]->value.string.string;
79     size= params[1]->value.number;
80     width= params[2]->value.number;
81   }
82   else
83     syntax_error(con);
84 
85   if (!memid ||
86       !*memid)
87     con->dd_printf("Wrong id\n");
88   else if ((size < 1) ||
89 	   (size > max_mem_size))
90     con->dd_printf("Wrong size\n");
91   else if ((width < 1) ||
92 	   (width > 32))
93     con->dd_printf("Wrong width\n");
94   else
95     {
96       class cl_memory *mem= new cl_memory_chip(memid, size, width);
97       mem->init();
98       uc->memchips->add(mem);
99       mem->set_uc(uc);
100     }
101   return(false);
102 }
103 
104 CMDHELP(cl_memory_create_chip_cmd,
105 	"memory create chip id size cellsize",
106 	"Create a new memory chip",
107 	"long help of memory create chip")
108 
109 /*
110  * Command: memory create addressspace
111  *----------------------------------------------------------------------------
112  */
113 
114 //int
115 //cl_conf_addmem_cmd::do_work(class cl_sim *sim,
116 //			    class cl_cmdline *cmdline, class cl_console *con)
COMMAND_DO_WORK_UC(cl_memory_create_addressspace_cmd)117 COMMAND_DO_WORK_UC(cl_memory_create_addressspace_cmd)
118 {
119   class cl_cmd_arg *params[4]= { cmdline->param(0),
120 				 cmdline->param(1),
121 				 cmdline->param(2),
122 				 cmdline->param(3) };
123   char *memid= NULL;
124   int start= 0, size= -1, width= 8;
125 
126   if (cmdline->syntax_match(uc, STRING NUMBER)) {
127     memid= params[0]->value.string.string;
128     size= params[1]->value.number;
129   }
130   else if (cmdline->syntax_match(uc, STRING NUMBER NUMBER)) {
131     memid= params[0]->value.string.string;
132     start= params[1]->value.number;
133     size= params[2]->value.number;
134   }
135   else if (cmdline->syntax_match(uc, STRING NUMBER NUMBER NUMBER)) {
136     memid= params[0]->value.string.string;
137     start= params[1]->value.number;
138     size= params[2]->value.number;
139     width= params[3]->value.number;
140   }
141   else
142     syntax_error(con);
143 
144   if (!memid ||
145       !*memid)
146     con->dd_printf("Wrong id\n");
147   else if ((size < 1) ||
148 	   (size > max_mem_size))
149     con->dd_printf("Wrong size\n");
150   else if ((width < 1) ||
151 	   (width > 32))
152     con->dd_printf("Wrong width\n");
153   else
154     {
155       class cl_address_space *mem=
156 	new cl_address_space(memid, start, size, width);
157       mem->init();
158       uc->address_spaces->add(mem);
159       mem->set_uc(uc);
160     }
161   return(false);
162 }
163 
164 CMDHELP(cl_memory_create_addressspace_cmd,
165 	"memory create addressspace id startaddr size",
166 	"Create a new address space",
167 	"long help of memory create addressspace")
168 
169 /*
170  * Command: memory create addressdecoder
171  *----------------------------------------------------------------------------
172  */
173 
174 //int
175 //cl_conf_addmem_cmd::do_work(class cl_sim *sim,
176 //			    class cl_cmdline *cmdline, class cl_console *con)
COMMAND_DO_WORK_UC(cl_memory_create_addressdecoder_cmd)177 COMMAND_DO_WORK_UC(cl_memory_create_addressdecoder_cmd)
178 {
179   class cl_cmd_arg *params[5]= { cmdline->param(0),
180 				 cmdline->param(1),
181 				 cmdline->param(2),
182 				 cmdline->param(3),
183 				 cmdline->param(4) };
184   class cl_memory *as= 0, *chip= 0;
185   t_addr as_begin= 0, as_end= 0, chip_begin= 0;
186 
187   if (cmdline->syntax_match(uc, MEMORY MEMORY)) {
188     as= params[0]->value.memory.memory;
189     as_end= as->highest_valid_address();
190     chip= params[1]->value.memory.memory;
191   }
192   else if (cmdline->syntax_match(uc, MEMORY MEMORY NUMBER)) {
193     as= params[0]->value.memory.memory;
194     as_end= as->highest_valid_address();
195     chip= params[1]->value.memory.memory;
196     chip_begin= params[2]->value.number;
197   }
198   else if (cmdline->syntax_match(uc, MEMORY NUMBER MEMORY)) {
199     as= params[0]->value.memory.memory;
200     as_begin= params[1]->value.number;
201     as_end= as->highest_valid_address();
202     chip= params[2]->value.memory.memory;
203   }
204   else if (cmdline->syntax_match(uc, MEMORY NUMBER MEMORY NUMBER)) {
205     as= params[0]->value.memory.memory;
206     as_begin= params[1]->value.number;
207     as_end= as->highest_valid_address();
208     chip= params[2]->value.memory.memory;
209     chip_begin= params[3]->value.number;
210   }
211   else if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY)) {
212     as= params[0]->value.memory.memory;
213     as_begin= params[1]->value.number;
214     as_end= params[2]->value.number;
215     chip= params[3]->value.memory.memory;
216   }
217   else if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY NUMBER)) {
218     as= params[0]->value.memory.memory;
219     as_begin= params[1]->value.number;
220     as_end= params[2]->value.number;
221     chip= params[3]->value.memory.memory;
222     chip_begin= params[4]->value.number;
223   }
224   else
225     syntax_error(con);
226 
227   if (!as->is_address_space())
228     con->dd_printf("%s is not an address space\n", as->get_name("unknown"));
229   else if (!chip->is_chip())
230     con->dd_printf("%s is not a memory chip\n", chip->get_name("unknown"));
231   else if (as_begin > as_end)
232     con->dd_printf("Wrong address area specification\n");
233   else if (chip_begin >= chip->get_size())
234     con->dd_printf("Wrong chip area specification\n");
235   else if (as_begin < as->start_address ||
236            as_end > as->highest_valid_address())
237     con->dd_printf("Specified area is out of address space\n");
238   else if (as_end-as_begin > chip->get_size()-chip_begin)
239     con->dd_printf("Specified area is out of chip size\n");
240   else
241     {
242       class cl_address_decoder *d=
243 	new cl_address_decoder(as, chip, as_begin, as_end, chip_begin);
244       d->init();
245       ((class cl_address_space *)as)->decoders->add(d);
246       d->activate(con);
247     }
248   return(false);
249 }
250 
251 CMDHELP(cl_memory_create_addressdecoder_cmd,
252 	"memory create addressdecoder addressspace begin end chip begin",
253 	"Create a new address decoder",
254 	"long help of memory create addressdecoder")
255 
256 /*
257  * Command: memory create banker
258  *----------------------------------------------------------------------------
259  */
260 
COMMAND_DO_WORK_UC(cl_memory_create_banker_cmd)261 COMMAND_DO_WORK_UC(cl_memory_create_banker_cmd)
262 {
263   class cl_cmd_arg *params[6]= { cmdline->param(0),
264 				 cmdline->param(1),
265 				 cmdline->param(2),
266 				 cmdline->param(3),
267 				 cmdline->param(4),
268 				 cmdline->param(5) };
269   class cl_memory *banker_as= 0, *banked_as= 0;
270   t_addr addr= 0, asb= 0, ase= 0;
271   t_mem mask= 0;
272 
273   if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY NUMBER NUMBER)) {
274     banker_as= params[0]->value.memory.memory;
275     addr= params[1]->value.number;
276     mask= params[2]->value.number;
277     banked_as= params[3]->value.memory.memory;
278     asb= params[4]->value.number;
279     ase= params[5]->value.number;
280   }
281   else
282     return syntax_error(con), false;
283 
284   if (!banker_as->is_address_space())
285     con->dd_printf("%s is not an address space\n", banker_as->get_name("unknown"));
286   else if (!banked_as->is_address_space())
287     con->dd_printf("%s is not an address space\n", banked_as->get_name("unknown"));
288   else if (addr < banker_as->start_address ||
289            addr > banker_as->highest_valid_address())
290     con->dd_printf("Specified banker address is out of address space\n");
291   else if (asb < banked_as->start_address ||
292            asb > banked_as->highest_valid_address())
293     con->dd_printf("Specified banked start address is out of address space\n");
294   else if (ase < banked_as->start_address ||
295            ase > banked_as->highest_valid_address())
296     con->dd_printf("Specified banked end address is out of address space\n");
297   else
298     {
299       class cl_banker *d=
300 	new cl_banker((class cl_address_space *)banker_as, addr, mask, //0,
301 		      (class cl_address_space *)banked_as, asb, ase);
302       d->init();
303       ((class cl_address_space *)banked_as)->decoders->add(d);
304       ((class cl_address_space *)banked_as)->undecode_area(d, asb, ase, con);
305       d->activate(con);
306     }
307   return(false);
308 }
309 
310 CMDHELP(cl_memory_create_banker_cmd,
311 	"memory create banker switcher_addressspace switcher_address switcher_mask banked_addressspace start end",
312 	"Create a new bank switcher",
313 	"long help of memory create banker")
314 
315 /*
316  * Command: memory create bander
317  *----------------------------------------------------------------------------
318  */
319 
COMMAND_DO_WORK_UC(cl_memory_create_bander_cmd)320 COMMAND_DO_WORK_UC(cl_memory_create_bander_cmd)
321 {
322   class cl_cmd_arg *params[7]= { cmdline->param(0),
323 				 cmdline->param(1),
324 				 cmdline->param(2),
325 				 cmdline->param(3),
326 				 cmdline->param(4),
327 				 cmdline->param(5),
328 				 cmdline->param(6) };
329   class cl_memory *as= 0;
330   t_addr asb= 0, ase= 0;
331   class cl_memory *chip= 0;
332   t_addr cb= 0;
333   int bpc= 0, dist= 1;
334 
335   if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY NUMBER NUMBER NUMBER))
336     {
337       as= params[0]->value.memory.memory;
338       asb= params[1]->value.number;
339       ase= params[2]->value.number;
340       chip= params[3]->value.memory.memory;
341       cb= params[4]->value.number;
342       bpc= params[5]->value.number;
343       dist= params[6]->value.number;
344     }
345   else if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY NUMBER NUMBER))
346     {
347       as= params[0]->value.memory.memory;
348       asb= params[1]->value.number;
349       ase= params[2]->value.number;
350       chip= params[3]->value.memory.memory;
351       cb= params[4]->value.number;
352       bpc= params[5]->value.number;
353     }
354   else
355     return syntax_error(con), false;
356 
357   if (!as->is_address_space())
358     con->dd_printf("%s is not an address space\n", as->get_name("unknown"));
359   else if (!chip->is_chip())
360     con->dd_printf("%s is not a chip\n", chip->get_name("unknown"));
361   else if (asb < as->start_address ||
362            asb > as->highest_valid_address())
363     con->dd_printf("Specified begin address is out of address space\n");
364   else if (ase < as->start_address ||
365            ase > as->highest_valid_address())
366     con->dd_printf("Specified end address is out of address space\n");
367   else if (cb < chip->start_address ||
368            cb > chip->highest_valid_address())
369     con->dd_printf("Specified chip address is out of size\n");
370   else
371     {
372       class cl_bander *b=
373 	new cl_bander((class cl_address_space *)as, asb, ase,
374 		      (class cl_memory_chip *)chip, cb,
375 		      bpc, dist);
376       b->init();
377       ((class cl_address_space *)as)->decoders->add(b);
378       b->activate(con);
379     }
380   return(false);
381 }
382 
383 CMDHELP(cl_memory_create_bander_cmd,
384 	"memory create bander addressspace begin end chip begin bits_per_chip [distance]",
385 	"Create a new bit bander",
386 	"long help of memory create bander")
387 
388 /*
389  * Command: memory create bank
390  *----------------------------------------------------------------------------
391  */
392 
COMMAND_DO_WORK_UC(cl_memory_create_bank_cmd)393 COMMAND_DO_WORK_UC(cl_memory_create_bank_cmd)
394 {
395   class cl_cmd_arg *params[5]= { cmdline->param(0),
396 				 cmdline->param(1),
397 				 cmdline->param(2),
398 				 cmdline->param(3),
399 				 cmdline->param(4) };
400   class cl_memory *as= 0, *chip= 0;
401   t_addr as_begin= 0, chip_begin= 0;
402   int bank= -1;
403 
404   if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY NUMBER)) {
405     as= params[0]->value.memory.memory;
406     as_begin= params[1]->value.number;
407     bank= params[2]->value.number;
408     chip= params[3]->value.memory.memory;
409     chip_begin= params[4]->value.number;
410   }
411   else if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER MEMORY)) {
412     as= params[0]->value.memory.memory;
413     as_begin= params[1]->value.number;
414     bank= params[2]->value.number;
415     chip= params[3]->value.memory.memory;
416   }
417   else
418     return syntax_error(con), false;
419 
420   if (!as->is_address_space())
421     con->dd_printf("%s is not an address space\n", as->get_name("unknown"));
422   else if (!chip->is_chip())
423     con->dd_printf("%s is not a memory chip\n", chip->get_name("unknown"));
424   else if (chip_begin >= chip->get_size())
425     con->dd_printf("Wrong chip area specification\n");
426   else if (as_begin < as->start_address ||
427            as_begin > as->highest_valid_address())
428     con->dd_printf("Specified area is out of address space\n");
429   else
430     {
431       class cl_banker *d=
432 	(class cl_banker *)((class cl_address_space *)as)->get_decoder_of(as_begin);
433       if (!d)
434 	con->dd_printf("Specified address is not decoded, create a banker first\n");
435       else if (!d->is_banker())
436 	con->dd_printf("Specified area is not decoded by banker\n");
437       else
438 	{
439 	  d->add_bank(bank, chip, chip_begin);
440 	}
441     }
442   return(false);
443 }
444 
445 CMDHELP(cl_memory_create_bank_cmd,
446 	"memory create bank addressspace begin bank_nr chip begin",
447 	"Add a new bank to bank switcher",
448 	"long help of memory create bank")
449 
450 /*
451  * Command: memory cell
452  *----------------------------------------------------------------------------
453  */
454 
COMMAND_DO_WORK_UC(cl_memory_cell_cmd)455 COMMAND_DO_WORK_UC(cl_memory_cell_cmd)
456 {
457   class cl_cmd_arg *params[5]= { cmdline->param(0),
458 				 cmdline->param(1) };
459   class cl_memory *m= 0;
460   t_addr a= 0;
461   class cl_address_space *as= 0;
462   class cl_memory_cell *c= 0;
463 
464   if (cmdline->syntax_match(uc, CELL))
465     {
466       c= params[0]->value.cell;
467       m= as= uc->address_space(c, &a);
468     }
469   else if (cmdline->syntax_match(uc, MEMORY ADDRESS /*NUMBER*/))
470     {
471       m= params[0]->value.memory.memory;
472       a= params[1]->value.number;
473       if (m->is_address_space())
474 	as= (cl_address_space *)m;
475     }
476   if (as == 0)
477     return syntax_error(con), false;
478 
479   if (!c)
480     c= as->get_cell(a);
481   con->dd_printf("%s", as->get_name());
482   con->dd_printf("[");
483   con->dd_printf(as->addr_format, a);
484   con->dd_printf("] %s\n", (char*)uc->cell_name(c));
485 
486   con->dd_printf("cell data=%p/%d mask=%x flags=%x\n",
487 		 c->get_data(),
488 		 MU(c->get_width()),
489 		 MU(c->get_mask()),
490 		 MU(c->get_flags()));
491 
492   int i;
493   for (i= 0; i < uc->memchips->count; i++)
494     {
495       cl_memory_chip *ch= (cl_memory_chip*)(uc->memchips->at(i));
496       t_addr ad;
497       if ((ad= ch->is_slot(c->get_data())) >= 0)
498 	{
499 	  con->dd_printf("  decoded to %s[%u]\n",
500 			 ch->get_name(), AU(ad));
501 	  break;
502 	}
503     }
504 
505   con->dd_printf("Operators:\n");
506   c->print_operators(" ", con);
507 
508   return false;
509 }
510 
511 CMDHELP(cl_memory_cell_cmd,
512 	"memory cell",
513 	"Information about a memory cell",
514 	"long help of memory cell")
515 
516 /* End of cmd.src/cmd_mem.cc */
517