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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [sim/] [common/] [sim-hw.c] - Blame information for rev 299

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

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

powered by: WebSVN 2.1.0

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