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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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