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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [sim/] [common/] [sim-hw.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 106 markom
/* Simulator hardware option handling.
2
   Copyright (C) 1998 Free Software Foundation, Inc.
3
   Contributed by Cygnus Support and Andrew Cagney.
4
 
5
This file is part of GDB, the GNU debugger.
6
 
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License along
18
with this program; if not, write to the Free Software Foundation, Inc.,
19
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include "sim-main.h"
22
#include "sim-assert.h"
23
#include "sim-options.h"
24
 
25
#include "sim-hw.h"
26
 
27
#include "hw-tree.h"
28
#include "hw-device.h"
29
#include "hw-main.h"
30
#include "hw-base.h"
31
 
32
 
33
#ifdef HAVE_STRING_H
34
#include <string.h>
35
#else
36
#ifdef HAVE_STRINGS_H
37
#include <strings.h>
38
#endif
39
#endif
40
#ifdef HAVE_STDLIB_H
41
#include <stdlib.h>
42
#endif
43
#include <ctype.h>
44
#include <sys/errno.h>
45
 
46
 
47
struct sim_hw {
48
  struct hw *tree;
49
  int trace_p;
50
  int info_p;
51
  /* if called from a processor */
52
  sim_cpu *cpu;
53
  sim_cia cia;
54
};
55
 
56
 
57
struct hw *
58
sim_hw_parse (struct sim_state *sd,
59
              const char *fmt,
60
              ...)
61
{
62
  struct hw *current;
63
  va_list ap;
64
  va_start (ap, fmt);
65
  current = hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap);
66
  va_end (ap);
67
  return current;
68
}
69
 
70
struct printer {
71
  struct sim_state *file;
72
  void (*print) (struct sim_state *, const char *, va_list ap);
73
};
74
 
75
static void
76
do_print (void *file, const char *fmt, ...)
77
{
78
  struct printer *p = file;
79
  va_list ap;
80
  va_start (ap, fmt);
81
  p->print (p->file, fmt, ap);
82
  va_end (ap);
83
}
84
 
85
void
86
sim_hw_print (struct sim_state *sd,
87
              void (*print) (struct sim_state *, const char *, va_list ap))
88
{
89
  struct printer p;
90
  p.file = sd;
91
  p.print = print;
92
  hw_tree_print (STATE_HW (sd)->tree, do_print, &p);
93
}
94
 
95
 
96
 
97
 
98
/* command line options. */
99
 
100
enum {
101
  OPTION_HW_INFO = OPTION_START,
102
  OPTION_HW_TRACE,
103
  OPTION_HW_DEVICE,
104
  OPTION_HW_FILE,
105
};
106
 
107
static DECLARE_OPTION_HANDLER (hw_option_handler);
108
 
109
static const OPTION hw_options[] =
110
{
111
  { {"hw-info", no_argument, NULL, OPTION_HW_INFO },
112
      '\0', NULL, "List configurable hw regions",
113
      hw_option_handler },
114
  { {"info-hw", no_argument, NULL, OPTION_HW_INFO },
115
      '\0', NULL, NULL,
116
      hw_option_handler },
117
 
118
  { {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE },
119
      '\0', "on|off", "Trace all hardware devices",
120
      hw_option_handler },
121
  { {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE },
122
      '\0', NULL, NULL,
123
      hw_option_handler },
124
 
125
  { {"hw-device", required_argument, NULL, OPTION_HW_DEVICE },
126
      '\0', "DEVICE", "Add the specified device",
127
      hw_option_handler },
128
 
129
  { {"hw-file", required_argument, NULL, OPTION_HW_FILE },
130
      '\0', "FILE", "Add the devices listed in the file",
131
      hw_option_handler },
132
 
133
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
134
};
135
 
136
 
137
 
138
/* Copied from ../ppc/psim.c:psim_merge_device_file() */
139
 
140
static SIM_RC
141
merge_device_file (struct sim_state *sd,
142
                   const char *file_name)
143
{
144
  FILE *description;
145
  struct hw *current = STATE_HW (sd)->tree;
146
  int line_nr;
147
  char device_path[1000];
148
 
149
  /* try opening the file */
150
  description = fopen (file_name, "r");
151
  if (description == NULL)
152
    {
153
      perror (file_name);
154
      return SIM_RC_FAIL;
155
    }
156
 
157
  line_nr = 0;
158
  while (fgets (device_path, sizeof(device_path), description))
159
    {
160
      char *device;
161
      /* check that a complete line was read */
162
      if (strchr (device_path, '\n') == NULL)
163
        {
164
          fclose (description);
165
          sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
166
          return SIM_RC_FAIL;
167
        }
168
      *strchr (device_path, '\n') = '\0';
169
      line_nr++;
170
      /* skip comments ("#" or ";") and blank lines lines */
171
      for (device = device_path;
172
           *device != '\0' && isspace (*device);
173
           device++);
174
      if (device[0] == '#'
175
          || device[0] == ';'
176
          || device[0] == '\0')
177
        continue;
178
      /* merge any appended lines */
179
      while (device_path[strlen (device_path) - 1] == '\\')
180
        {
181
          int curlen = strlen (device_path) - 1;
182
          /* zap the `\' at the end of the line */
183
          device_path[curlen] = '\0';
184
          /* append the next line */
185
          if (!fgets (device_path + curlen,
186
                      sizeof (device_path) - curlen,
187
                      description))
188
            {
189
              fclose (description);
190
              sim_io_eprintf (sd, "%s:%d: unexpected eof", file_name, line_nr);
191
              return SIM_RC_FAIL;
192
            }
193
          if (strchr(device_path, '\n') == NULL)
194
            {
195
              fclose(description);
196
              sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
197
              return SIM_RC_FAIL;
198
            }
199
          *strchr(device_path, '\n') = '\0';
200
          line_nr++;
201
        }
202
      /* parse this line */
203
      current = hw_tree_parse (current, "%s", device);
204
    }
205
  fclose (description);
206
  return SIM_RC_OK;
207
}
208
 
209
 
210
static SIM_RC
211
hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt,
212
                   char *arg, int is_command)
213
{
214
  switch (opt)
215
    {
216
 
217
    case OPTION_HW_INFO:
218
      {
219
        /* delay info until after the tree is finished */
220
        STATE_HW (sd)->info_p = 1;
221
        return SIM_RC_OK;
222
        break;
223
      }
224
 
225
    case OPTION_HW_TRACE:
226
      {
227
        if (arg == NULL)
228
          {
229
            STATE_HW (sd)->trace_p = 1;
230
          }
231
        else if (strcmp (arg, "yes") == 0
232
                 || strcmp (arg, "on") == 0)
233
          {
234
            STATE_HW (sd)->trace_p = 1;
235
          }
236
        else if (strcmp (arg, "no") == 0
237
                 || strcmp (arg, "off") == 0)
238
          {
239
            STATE_HW (sd)->trace_p = 0;
240
          }
241
        else
242
          {
243
            sim_io_eprintf (sd, "Option --hw-trace ignored\n");
244
            /* set tracing on all devices */
245
            return SIM_RC_FAIL;
246
          }
247
        /* FIXME: Not very nice - see also hw-base.c */
248
        if (STATE_HW (sd)->trace_p)
249
          hw_tree_parse (STATE_HW (sd)->tree, "/global-trace? true");
250
        return SIM_RC_OK;
251
        break;
252
      }
253
 
254
    case OPTION_HW_DEVICE:
255
      {
256
        hw_tree_parse (STATE_HW (sd)->tree, arg);
257
        return SIM_RC_OK;
258
      }
259
 
260
    case OPTION_HW_FILE:
261
      {
262
        return merge_device_file (sd, arg);
263
      }
264
 
265
    default:
266
      sim_io_eprintf (sd, "Unknown hw option %d\n", opt);
267
      return SIM_RC_FAIL;
268
 
269
    }
270
 
271
  return SIM_RC_FAIL;
272
}
273
 
274
 
275
/* "hw" module install handler.
276
 
277
   This is called via sim_module_install to install the "hw" subsystem
278
   into the simulator.  */
279
 
280
static MODULE_INIT_FN sim_hw_init;
281
static MODULE_UNINSTALL_FN sim_hw_uninstall;
282
 
283
SIM_RC
284
sim_hw_install (struct sim_state *sd)
285
{
286
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
287
  sim_add_option_table (sd, NULL, hw_options);
288
  sim_module_add_uninstall_fn (sd, sim_hw_uninstall);
289
  sim_module_add_init_fn (sd, sim_hw_init);
290
  STATE_HW (sd) = ZALLOC (struct sim_hw);
291
  STATE_HW (sd)->tree = hw_tree_create (sd, "core");
292
  return SIM_RC_OK;
293
}
294
 
295
 
296
static SIM_RC
297
sim_hw_init (struct sim_state *sd)
298
{
299
  /* FIXME: anything needed? */
300
  hw_tree_finish (STATE_HW (sd)->tree);
301
  if (STATE_HW (sd)->info_p)
302
    sim_hw_print (sd, sim_io_vprintf);
303
  return SIM_RC_OK;
304
}
305
 
306
/* Uninstall the "hw" subsystem from the simulator.  */
307
 
308
static void
309
sim_hw_uninstall (struct sim_state *sd)
310
{
311
  /* hw_tree_delete (STATE_HW (sd)->tree); */
312
  zfree (STATE_HW (sd));
313
  STATE_HW (sd) = NULL;
314
}
315
 
316
 
317
 
318
/* Data transfers to/from the hardware device tree.  There are several
319
   cases. */
320
 
321
 
322
/* CPU: The simulation is running and the current CPU/CIA
323
   initiates a data transfer. */
324
 
325
void
326
sim_cpu_hw_io_read_buffer (sim_cpu *cpu,
327
                           sim_cia cia,
328
                           struct hw *hw,
329
                           void *dest,
330
                           int space,
331
                           unsigned_word addr,
332
                           unsigned nr_bytes)
333
{
334
  SIM_DESC sd = CPU_STATE (cpu);
335
  STATE_HW (sd)->cpu = cpu;
336
  STATE_HW (sd)->cia = cia;
337
  if (hw_io_read_buffer (hw, dest, space, addr, nr_bytes) != nr_bytes)
338
    sim_engine_abort (sd, cpu, cia, "broken CPU read");
339
}
340
 
341
void
342
sim_cpu_hw_io_write_buffer (sim_cpu *cpu,
343
                            sim_cia cia,
344
                            struct hw *hw,
345
                            const void *source,
346
                            int space,
347
                            unsigned_word addr,
348
                            unsigned nr_bytes)
349
{
350
  SIM_DESC sd = CPU_STATE (cpu);
351
  STATE_HW (sd)->cpu = cpu;
352
  STATE_HW (sd)->cia = cia;
353
  if (hw_io_write_buffer (hw, source, space, addr, nr_bytes) != nr_bytes)
354
    sim_engine_abort (sd, cpu, cia, "broken CPU write");
355
}
356
 
357
 
358
 
359
 
360
/* SYSTEM: A data transfer is being initiated by the system. */
361
 
362
unsigned
363
sim_hw_io_read_buffer (struct sim_state *sd,
364
                       struct hw *hw,
365
                       void *dest,
366
                       int space,
367
                       unsigned_word addr,
368
                       unsigned nr_bytes)
369
{
370
  STATE_HW (sd)->cpu = NULL;
371
  return hw_io_read_buffer (hw, dest, space, addr, nr_bytes);
372
}
373
 
374
unsigned
375
sim_hw_io_write_buffer (struct sim_state *sd,
376
                        struct hw *hw,
377
                        const void *source,
378
                        int space,
379
                        unsigned_word addr,
380
                        unsigned nr_bytes)
381
{
382
  STATE_HW (sd)->cpu = NULL;
383
  return hw_io_write_buffer (hw, source, space, addr, nr_bytes);
384
}
385
 
386
 
387
 
388
/* Abort the simulation specifying HW as the reason */
389
 
390
void
391
hw_vabort (struct hw *me,
392
           const char *fmt,
393
           va_list ap)
394
{
395
  const char *name;
396
  char *msg;
397
  /* find an identity */
398
  if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
399
    name = hw_path (me);
400
  else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
401
    name = hw_name (me);
402
  else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
403
    name = hw_family (me);
404
  else
405
    name = "device";
406
  /* construct an updated format string */
407
  msg = alloca (strlen (name) + strlen (": ") + strlen (fmt) + 1);
408
  strcpy (msg, name);
409
  strcat (msg, ": ");
410
  strcat (msg, fmt);
411
  /* report the problem */
412
  sim_engine_vabort (hw_system (me),
413
                     STATE_HW (hw_system (me))->cpu,
414
                     STATE_HW (hw_system (me))->cia,
415
                     msg, ap);
416
}
417
 
418
void
419
hw_abort (struct hw *me,
420
          const char *fmt,
421
          ...)
422
{
423
  va_list ap;
424
  /* report the problem */
425
  va_start (ap, fmt);
426
  hw_vabort (me, fmt, ap);
427
  va_end (ap);
428
}
429
 
430
void
431
sim_hw_abort (struct sim_state *sd,
432
              struct hw *me,
433
              const char *fmt,
434
              ...)
435
{
436
  va_list ap;
437
  va_start (ap, fmt);
438
  if (me == NULL)
439
    sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap);
440
  else
441
    hw_vabort (me, fmt, ap);
442
  va_end (ap);
443
}
444
 
445
 
446
/* MISC routines to tie HW into the rest of the system */
447
 
448
void
449
hw_halt (struct hw *me,
450
         int reason,
451
         int status)
452
{
453
  struct sim_state *sd = hw_system (me);
454
  struct sim_hw *sim = STATE_HW (sd);
455
  sim_engine_halt (sd, sim->cpu, NULL, sim->cia, reason, status);
456
}
457
 
458
struct _sim_cpu *
459
hw_system_cpu (struct hw *me)
460
{
461
  return STATE_HW (hw_system (me))->cpu;
462
}
463
 
464
void
465
hw_trace (struct hw *me,
466
          const char *fmt,
467
          ...)
468
{
469
  if (hw_trace_p (me)) /* to be sure, to be sure */
470
    {
471
      va_list ap;
472
      va_start (ap, fmt);
473
      sim_io_eprintf (hw_system (me), "%s: ", hw_path (me));
474
      sim_io_evprintf (hw_system (me), fmt, ap);
475
      sim_io_eprintf (hw_system (me), "\n");
476
      va_end (ap);
477
    }
478
}
479
 
480
 
481
/* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */
482
 
483
int
484
do_hw_poll_read (struct hw *me,
485
                 do_hw_poll_read_method *read,
486
                 int sim_io_fd,
487
                 void *buf,
488
                 unsigned sizeof_buf)
489
{
490
  int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf);
491
  if (status > 0)
492
    return status;
493
  else if (status == 0 && sizeof_buf == 0)
494
    return 0;
495
  else if (status == 0)
496
    return HW_IO_EOF;
497
  else /* status < 0 */
498
    {
499
#ifdef EAGAIN
500
      if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN)
501
        return HW_IO_NOT_READY;
502
      else
503
        return HW_IO_EOF;
504
#else
505
      return HW_IO_EOF;
506
#endif
507
    }
508
}

powered by: WebSVN 2.1.0

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