OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [common/] [dv-pal.c] - Blame information for rev 280

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.