1 /* Simulator hardware option handling.
2 Copyright (C) 1998, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4 Contributed by Cygnus Support and Andrew Cagney.
6 This file is part of GDB, the GNU debugger.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "sim-assert.h"
23 #include "sim-options.h"
28 #include "hw-device.h"
51 /* if called from a processor */
58 sim_hw_parse (struct sim_state *sd,
65 current = hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap);
71 struct sim_state *file;
72 void (*print) (struct sim_state *, const char *, va_list ap);
76 do_print (void *file, const char *fmt, ...)
78 struct printer *p = file;
81 p->print (p->file, fmt, ap);
86 sim_hw_print (struct sim_state *sd,
87 void (*print) (struct sim_state *, const char *, va_list ap))
92 hw_tree_print (STATE_HW (sd)->tree, do_print, &p);
98 /* command line options. */
101 OPTION_HW_INFO = OPTION_START,
108 static DECLARE_OPTION_HANDLER (hw_option_handler);
110 static const OPTION hw_options[] =
112 { {"hw-info", no_argument, NULL, OPTION_HW_INFO },
113 '\0', NULL, "List configurable hw regions",
114 hw_option_handler, NULL },
115 { {"info-hw", no_argument, NULL, OPTION_HW_INFO },
117 hw_option_handler, NULL },
119 { {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE },
120 '\0', "on|off", "Trace all hardware devices",
121 hw_option_handler, NULL },
122 { {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE },
124 hw_option_handler, NULL },
126 { {"hw-device", required_argument, NULL, OPTION_HW_DEVICE },
127 '\0', "DEVICE", "Add the specified device",
128 hw_option_handler, NULL },
130 { {"hw-list", no_argument, NULL, OPTION_HW_LIST },
131 '\0', NULL, "List the device tree",
132 hw_option_handler, NULL },
134 { {"hw-file", required_argument, NULL, OPTION_HW_FILE },
135 '\0', "FILE", "Add the devices listed in the file",
136 hw_option_handler, NULL },
138 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
143 /* Copied from ../ppc/psim.c:psim_merge_device_file() */
146 merge_device_file (struct sim_state *sd,
147 const char *file_name)
150 struct hw *current = STATE_HW (sd)->tree;
152 char device_path[1000];
154 /* try opening the file */
155 description = fopen (file_name, "r");
156 if (description == NULL)
163 while (fgets (device_path, sizeof (device_path), description))
166 /* check that a complete line was read */
167 if (strchr (device_path, '\n') == NULL)
169 fclose (description);
170 sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
173 *strchr (device_path, '\n') = '\0';
175 /* skip comments ("#" or ";") and blank lines lines */
176 for (device = device_path;
177 *device != '\0' && isspace (*device);
181 || device[0] == '\0')
183 /* merge any appended lines */
184 while (device_path[strlen (device_path) - 1] == '\\')
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,
194 fclose (description);
195 sim_io_eprintf (sd, "%s:%d: unexpected eof", file_name, line_nr);
198 if (strchr (device_path, '\n') == NULL)
200 fclose (description);
201 sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
204 *strchr (device_path, '\n') = '\0';
207 /* parse this line */
208 current = hw_tree_parse (current, "%s", device);
210 fclose (description);
216 hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt,
217 char *arg, int is_command)
224 /* delay info until after the tree is finished */
225 STATE_HW (sd)->info_p = 1;
230 case OPTION_HW_TRACE:
234 STATE_HW (sd)->trace_p = 1;
236 else if (strcmp (arg, "yes") == 0
237 || strcmp (arg, "on") == 0)
239 STATE_HW (sd)->trace_p = 1;
241 else if (strcmp (arg, "no") == 0
242 || strcmp (arg, "off") == 0)
244 STATE_HW (sd)->trace_p = 0;
248 sim_io_eprintf (sd, "Option --hw-trace ignored\n");
249 /* set tracing on all devices */
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");
259 case OPTION_HW_DEVICE:
261 hw_tree_parse (STATE_HW (sd)->tree, "%s", arg);
267 sim_hw_print (sd, sim_io_vprintf);
273 return merge_device_file (sd, arg);
277 sim_io_eprintf (sd, "Unknown hw option %d\n", opt);
286 /* "hw" module install handler.
288 This is called via sim_module_install to install the "hw" subsystem
289 into the simulator. */
291 static MODULE_INIT_FN sim_hw_init;
292 static MODULE_UNINSTALL_FN sim_hw_uninstall;
295 sim_hw_install (struct sim_state *sd)
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");
308 sim_hw_init (struct sim_state *sd)
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);
317 /* Uninstall the "hw" subsystem from the simulator. */
320 sim_hw_uninstall (struct sim_state *sd)
322 hw_tree_delete (STATE_HW (sd)->tree);
323 free (STATE_HW (sd));
324 STATE_HW (sd) = NULL;
329 /* Data transfers to/from the hardware device tree. There are several
333 /* CPU: The simulation is running and the current CPU/CIA
334 initiates a data transfer. */
337 sim_cpu_hw_io_read_buffer (sim_cpu *cpu,
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");
353 sim_cpu_hw_io_write_buffer (sim_cpu *cpu,
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");
371 /* SYSTEM: A data transfer is being initiated by the system. */
374 sim_hw_io_read_buffer (struct sim_state *sd,
381 STATE_HW (sd)->cpu = NULL;
382 return hw_io_read_buffer (hw, dest, space, addr, nr_bytes);
386 sim_hw_io_write_buffer (struct sim_state *sd,
393 STATE_HW (sd)->cpu = NULL;
394 return hw_io_write_buffer (hw, source, space, addr, nr_bytes);
399 /* Abort the simulation specifying HW as the reason */
402 hw_vabort (struct hw *me,
408 /* find an identity */
409 if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
411 else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
413 else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
414 name = hw_family (me);
417 /* construct an updated format string */
418 msg = alloca (strlen (name) + strlen (": ") + strlen (fmt) + 1);
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,
430 hw_abort (struct hw *me,
435 /* report the problem */
437 hw_vabort (me, fmt, ap);
442 sim_hw_abort (struct sim_state *sd,
450 sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap);
452 hw_vabort (me, fmt, ap);
457 /* MISC routines to tie HW into the rest of the system */
460 hw_halt (struct hw *me,
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);
470 hw_system_cpu (struct hw *me)
472 return STATE_HW (hw_system (me))->cpu;
476 hw_trace (struct hw *me,
480 if (hw_trace_p (me)) /* to be sure, to be sure */
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");
492 /* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */
495 do_hw_poll_read (struct hw *me,
496 do_hw_poll_read_method *read,
501 int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf);
504 else if (status == 0 && sizeof_buf == 0)
506 else if (status == 0)
508 else /* status < 0 */
511 if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN)
512 return HW_IO_NOT_READY;