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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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