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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [dv-pal.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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