packaging: Add python3-base dependency
[platform/upstream/gdb.git] / sim / common / dv-pal.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3    Copyright 2002-2023 Free Software Foundation, Inc.
4
5    Contributed by Andrew Cagney and Red Hat.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 /* This must come before any other includes.  */
23 #include "defs.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #include "sim-main.h"
32 #include "hw-main.h"
33 #include "sim-io.h"
34
35 /* NOTE: pal is naughty and grubs around looking at things outside of
36    its immediate domain */
37 #include "hw-tree.h"
38
39 /* DEVICE
40
41
42    pal - glue logic device containing assorted junk
43
44
45    DESCRIPTION
46
47
48    Typical hardware dependant hack.  This device allows the firmware
49    to gain access to all the things the firmware needs (but the OS
50    doesn't).
51
52    The pal contains the following registers:
53
54    |0   reset register (write, 8bit)
55    |4   processor id register (read, 8bit)
56    |8   interrupt register (8 - port, 9 - level) (write, 16bit)
57    |12  processor count register (read, 8bit)
58
59    |16  tty input fifo register (read, 8bit)
60    |20  tty input status register (read, 8bit)
61    |24  tty output fifo register (write, 8bit)
62    |28  tty output status register (read, 8bit)
63
64    |32  countdown register (read/write, 32bit, big-endian)
65    |36  countdown value register (read, 32bit, big-endian)
66    |40  timer register (read/write, 32bit, big-endian)
67    |44  timer value register (read, 32bit, big-endian)
68
69    RESET (write): halts the simulator.  The value written to the
70    register is used as an exit status.
71
72    PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
73    the processor performing the read.
74
75    INTERRUPT (write): This register must be written using a two byte
76    store.  The low byte specifies a port and the upper byte specifies
77    the a level.  LEVEL is driven on the specified port.  By
78    convention, the pal's interrupt ports (int0, int1, ...) are wired
79    up to the corresponding processor's level sensative external
80    interrupt pin.  Eg: A two byte write to address 8 of 0x0102
81    (big-endian) will result in processor 2's external interrupt pin
82    being asserted.
83
84    PROCESSOR COUNT (read): returns the total number of processors
85    active in the current simulation.
86
87    TTY INPUT FIFO (read): if the TTY input status register indicates a
88    character is available by being nonzero, returns the next available
89    character from the pal's tty input port.
90
91    TTY OUTPUT FIFO (write): if the TTY output status register
92    indicates the output fifo is not full by being nonzero, outputs the
93    character written to the tty's output port.
94
95    COUNDOWN (read/write): The countdown registers provide a
96    non-repeating timed interrupt source.  Writing a 32 bit big-endian
97    zero value to this register clears the countdown timer.  Writing a
98    non-zero 32 bit big-endian value to this register sets the
99    countdown timer to expire in VALUE ticks (ticks is target
100    dependant).  Reading the countdown register returns the last value
101    writen.
102
103    COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
104    returns the number of ticks remaining until the countdown timer
105    expires.
106
107    TIMER (read/write): The timer registers provide a periodic timed
108    interrupt source.  Writing a 32 bit big-endian zero value to this
109    register clears the periodic timer.  Writing a 32 bit non-zero
110    value to this register sets the periodic timer to triger every
111    VALUE ticks (ticks is target dependant).  Reading the timer
112    register returns the last value written.
113
114    TIMER VALUE (read): Reading this 32 bit big-endian register returns
115    the number of ticks until the next periodic interrupt.
116
117
118    PROPERTIES
119
120
121    reg = <address> <size> (required)
122
123    Specify the address (within the parent bus) that this device is to
124    be located.
125
126    poll? = <boolean>
127
128    If present and true, indicates that the device should poll its
129    input.
130
131
132    PORTS
133
134
135    int[0..NR_PROCESSORS] (output)
136
137    Driven as a result of a write to the interrupt-port /
138    interrupt-level register pair.
139
140
141    countdown
142
143    Driven whenever the countdown counter reaches zero.
144
145
146    timer
147
148    Driven whenever the timer counter reaches zero.
149
150
151    BUGS
152
153
154    At present the common simulator framework does not support input
155    polling.
156
157    */
158
159
160 enum {
161   hw_pal_reset_register = 0x0,
162   hw_pal_cpu_nr_register = 0x4,
163   hw_pal_int_register = 0x8,
164   hw_pal_nr_cpu_register = 0xa,
165   hw_pal_read_fifo = 0x10,
166   hw_pal_read_status = 0x14,
167   hw_pal_write_fifo = 0x18,
168   hw_pal_write_status = 0x1a,
169   hw_pal_countdown = 0x20,
170   hw_pal_countdown_value = 0x24,
171   hw_pal_timer = 0x28,
172   hw_pal_timer_value = 0x2c,
173   hw_pal_address_mask = 0x3f,
174 };
175
176
177 typedef struct _hw_pal_console_buffer {
178   char buffer;
179   int status;
180 } hw_pal_console_buffer;
181
182 typedef struct _hw_pal_counter {
183   struct hw_event *handler;
184   int64_t start;
185   uint32_t delta;
186   int periodic_p;
187 } hw_pal_counter;
188
189
190 typedef struct _hw_pal_device {
191   hw_pal_console_buffer input;
192   hw_pal_console_buffer output;
193   hw_pal_counter countdown;
194   hw_pal_counter timer;
195   struct hw *disk;
196   do_hw_poll_read_method *reader;
197 } hw_pal_device;
198
199 enum {
200   COUNTDOWN_PORT,
201   TIMER_PORT,
202   INT_PORT,
203 };
204
205 static const struct hw_port_descriptor hw_pal_ports[] = {
206   { "countdown", COUNTDOWN_PORT, 0, output_port, },
207   { "timer", TIMER_PORT, 0, output_port, },
208   { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, },
209   { NULL, 0, 0, 0 }
210 };
211
212
213 /* countdown and simple timer */
214
215 static void
216 do_counter_event (struct hw *me,
217                   void *data)
218 {
219   hw_pal_counter *counter = (hw_pal_counter *) data;
220   if (counter->periodic_p)
221     {
222       HW_TRACE ((me, "timer expired"));
223       counter->start = hw_event_queue_time (me);
224       hw_port_event (me, TIMER_PORT, 1);
225       hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
226     }
227   else
228     {
229       HW_TRACE ((me, "countdown expired"));
230       counter->delta = 0;
231       hw_port_event (me, COUNTDOWN_PORT, 1);
232     }
233 }
234
235 static void
236 do_counter_read (struct hw *me,
237                  hw_pal_device *pal,
238                  const char *reg,
239                  hw_pal_counter *counter,
240                  uint32_t *word,
241                  unsigned nr_bytes)
242 {
243   uint32_t val;
244   if (nr_bytes != 4)
245     hw_abort (me, "%s - bad read size must be 4 bytes", reg);
246   val = counter->delta;
247   HW_TRACE ((me, "read - %s %ld", reg, (long) val));
248   *word = H2BE_4 (val);
249 }
250
251 static void
252 do_counter_value (struct hw *me,
253                   hw_pal_device *pal,
254                   const char *reg,
255                   hw_pal_counter *counter,
256                   uint32_t *word,
257                   unsigned nr_bytes)
258 {
259   uint32_t val;
260   if (nr_bytes != 4)
261     hw_abort (me, "%s - bad read size must be 4 bytes", reg);
262   if (counter->delta != 0)
263     val = (counter->start + counter->delta
264            - hw_event_queue_time (me));
265   else
266     val = 0;
267   HW_TRACE ((me, "read - %s %ld", reg, (long) val));
268   *word = H2BE_4 (val);
269 }
270
271 static void
272 do_counter_write (struct hw *me,
273                   hw_pal_device *pal,
274                   const char *reg,
275                   hw_pal_counter *counter,
276                   const uint32_t *word,
277                   unsigned nr_bytes)
278 {
279   if (nr_bytes != 4)
280     hw_abort (me, "%s - bad write size must be 4 bytes", reg);
281   if (counter->handler != NULL)
282     {
283       hw_event_queue_deschedule (me, counter->handler);
284       counter->handler = NULL;
285     }
286   counter->delta = BE2H_4 (*word);
287   counter->start = hw_event_queue_time (me);
288   HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta));
289   if (counter->delta > 0)
290     hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
291 }
292
293
294
295
296 /* check the console for an available character */
297 static void
298 scan_hw_pal (struct hw *me)
299 {
300   hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me);
301   char c;
302   int count;
303   count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof (c));
304   switch (count)
305     {
306     case HW_IO_NOT_READY:
307     case HW_IO_EOF:
308       hw_pal->input.buffer = 0;
309       hw_pal->input.status = 0;
310       break;
311     default:
312       hw_pal->input.buffer = c;
313       hw_pal->input.status = 1;
314     }
315 }
316
317 /* write the character to the hw_pal */
318
319 static void
320 write_hw_pal (struct hw *me,
321               char val)
322 {
323   hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
324   sim_io_write_stdout (hw_system (me), &val, 1);
325   hw_pal->output.buffer = val;
326   hw_pal->output.status = 1;
327 }
328
329
330 /* Reads/writes */
331
332 static unsigned
333 hw_pal_io_read_buffer (struct hw *me,
334                        void *dest,
335                        int space,
336                        unsigned_word addr,
337                        unsigned nr_bytes)
338 {
339   hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
340   unsigned_1 *byte = (unsigned_1 *) dest;
341   memset (dest, 0, nr_bytes);
342   switch (addr & hw_pal_address_mask)
343     {
344
345     case hw_pal_cpu_nr_register:
346       *byte = CPU_INDEX (hw_system_cpu (me));
347       HW_TRACE ((me, "read - cpu-nr %d\n", *byte));
348       break;
349
350     case hw_pal_nr_cpu_register:
351       if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
352         {
353           *byte = 1;
354           HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
355         }
356       else
357         {
358           *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
359           HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
360         }
361       break;
362
363     case hw_pal_read_fifo:
364       *byte = hw_pal->input.buffer;
365       HW_TRACE ((me, "read - input-fifo %d\n", *byte));
366       break;
367
368     case hw_pal_read_status:
369       scan_hw_pal (me);
370       *byte = hw_pal->input.status;
371       HW_TRACE ((me, "read - input-status %d\n", *byte));
372       break;
373
374     case hw_pal_write_fifo:
375       *byte = hw_pal->output.buffer;
376       HW_TRACE ((me, "read - output-fifo %d\n", *byte));
377       break;
378
379     case hw_pal_write_status:
380       *byte = hw_pal->output.status;
381       HW_TRACE ((me, "read - output-status %d\n", *byte));
382       break;
383
384     case hw_pal_countdown:
385       do_counter_read (me, hw_pal, "countdown",
386                        &hw_pal->countdown, dest, nr_bytes);
387       break;
388
389     case hw_pal_countdown_value:
390       do_counter_value (me, hw_pal, "countdown-value",
391                         &hw_pal->countdown, dest, nr_bytes);
392       break;
393
394     case hw_pal_timer:
395       do_counter_read (me, hw_pal, "timer",
396                        &hw_pal->timer, dest, nr_bytes);
397       break;
398
399     case hw_pal_timer_value:
400       do_counter_value (me, hw_pal, "timer-value",
401                         &hw_pal->timer, dest, nr_bytes);
402       break;
403
404     default:
405       HW_TRACE ((me, "read - ???\n"));
406       break;
407
408     }
409   return nr_bytes;
410 }
411
412
413 static unsigned
414 hw_pal_io_write_buffer (struct hw *me,
415                         const void *source,
416                         int space,
417                         unsigned_word addr,
418                         unsigned nr_bytes)
419 {
420   hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
421   unsigned_1 *byte = (unsigned_1 *) source;
422
423   switch (addr & hw_pal_address_mask)
424     {
425
426     case hw_pal_reset_register:
427       hw_halt (me, sim_exited, byte[0]);
428       break;
429
430     case hw_pal_int_register:
431       hw_port_event (me,
432                      INT_PORT + byte[0], /*port*/
433                      (nr_bytes > 1 ? byte[1] : 0)); /* val */
434       break;
435
436     case hw_pal_read_fifo:
437       hw_pal->input.buffer = byte[0];
438       HW_TRACE ((me, "write - input-fifo %d\n", byte[0]));
439       break;
440
441     case hw_pal_read_status:
442       hw_pal->input.status = byte[0];
443       HW_TRACE ((me, "write - input-status %d\n", byte[0]));
444       break;
445
446     case hw_pal_write_fifo:
447       write_hw_pal (me, byte[0]);
448       HW_TRACE ((me, "write - output-fifo %d\n", byte[0]));
449       break;
450
451     case hw_pal_write_status:
452       hw_pal->output.status = byte[0];
453       HW_TRACE ((me, "write - output-status %d\n", byte[0]));
454       break;
455
456     case hw_pal_countdown:
457       do_counter_write (me, hw_pal, "countdown",
458                         &hw_pal->countdown, source, nr_bytes);
459       break;
460
461     case hw_pal_timer:
462       do_counter_write (me, hw_pal, "timer",
463                         &hw_pal->timer, source, nr_bytes);
464       break;
465
466     }
467   return nr_bytes;
468 }
469
470
471 /* instances of the hw_pal struct hw */
472
473 #if NOT_YET
474 static void
475 hw_pal_instance_delete_callback (hw_instance *instance)
476 {
477   /* nothing to delete, the hw_pal is attached to the struct hw */
478   return;
479 }
480 #endif
481
482 #if NOT_YET
483 static int
484 hw_pal_instance_read_callback (hw_instance *instance,
485                               void *buf,
486                               unsigned_word len)
487 {
488   DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
489   return sim_io_read_stdin (buf, len);
490 }
491 #endif
492
493 #if NOT_YET
494 static int
495 hw_pal_instance_write_callback (hw_instance *instance,
496                                 const void *buf,
497                                 unsigned_word len)
498 {
499   int i;
500   const char *chp = buf;
501   hw_pal_device *hw_pal = hw_instance_data (instance);
502   DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len));
503   for (i = 0; i < len; i++)
504     write_hw_pal (hw_pal, chp[i]);
505   sim_io_flush_stdoutput ();
506   return i;
507 }
508 #endif
509
510 #if NOT_YET
511 static const hw_instance_callbacks hw_pal_instance_callbacks = {
512   hw_pal_instance_delete_callback,
513   hw_pal_instance_read_callback,
514   hw_pal_instance_write_callback,
515 };
516 #endif
517
518 #if 0
519 static hw_instance *
520 hw_pal_create_instance (struct hw *me,
521                         const char *path,
522                         const char *args)
523 {
524   return hw_create_instance_from (me, NULL,
525                                       hw_data (me),
526                                       path, args,
527                                       &hw_pal_instance_callbacks);
528 }
529 #endif
530
531
532 static void
533 hw_pal_attach_address (struct hw *me,
534                        int level,
535                        int space,
536                        address_word addr,
537                        address_word nr_bytes,
538                        struct hw *client)
539 {
540   hw_pal_device *pal = (hw_pal_device*) hw_data (me);
541   pal->disk = client;
542 }
543
544
545 #if 0
546 static hw_callbacks const hw_pal_callbacks = {
547   { generic_hw_init_address, },
548   { hw_pal_attach_address, }, /* address */
549   { hw_pal_io_read_buffer_callback,
550       hw_pal_io_write_buffer_callback, },
551   { NULL, }, /* DMA */
552   { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
553   { generic_hw_unit_decode,
554     generic_hw_unit_encode,
555     generic_hw_address_to_attach_address,
556     generic_hw_size_to_attach_size },
557   hw_pal_create_instance,
558 };
559 #endif
560
561
562 static void
563 hw_pal_finish (struct hw *hw)
564 {
565   /* create the descriptor */
566   hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device);
567   hw_pal->output.status = 1;
568   hw_pal->output.buffer = '\0';
569   hw_pal->input.status = 0;
570   hw_pal->input.buffer = '\0';
571   set_hw_data (hw, hw_pal);
572   set_hw_attach_address (hw, hw_pal_attach_address);
573   set_hw_io_read_buffer (hw, hw_pal_io_read_buffer);
574   set_hw_io_write_buffer (hw, hw_pal_io_write_buffer);
575   set_hw_ports (hw, hw_pal_ports);
576   /* attach ourselves */
577   do_hw_attach_regs (hw);
578   /* If so configured, enable polled input */
579   if (hw_find_property (hw, "poll?") != NULL
580       && hw_find_boolean_property (hw, "poll?"))
581     {
582       hw_pal->reader = sim_io_poll_read;
583     }
584   else
585     {
586       hw_pal->reader = sim_io_read;
587     }
588   /* tag the periodic timer */
589   hw_pal->timer.periodic_p = 1;
590 }
591
592
593 const struct hw_descriptor dv_pal_descriptor[] = {
594   { "pal", hw_pal_finish, },
595   { NULL, NULL },
596 };