1 /* Simulator hardware option handling.
2 Copyright (C) 1998, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3 Contributed by Cygnus Support and Andrew Cagney.
5 This file is part of GDB, the GNU debugger.
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.
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.
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/>. */
21 #include "sim-assert.h"
22 #include "sim-options.h"
27 #include "hw-device.h"
50 /* if called from a processor */
57 sim_hw_parse (struct sim_state *sd,
64 current = hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap);
70 struct sim_state *file;
71 void (*print) (struct sim_state *, const char *, va_list ap);
75 do_print (void *file, const char *fmt, ...)
77 struct printer *p = file;
80 p->print (p->file, fmt, ap);
85 sim_hw_print (struct sim_state *sd,
86 void (*print) (struct sim_state *, const char *, va_list ap))
91 hw_tree_print (STATE_HW (sd)->tree, do_print, &p);
97 /* command line options. */
100 OPTION_HW_INFO = OPTION_START,
107 static DECLARE_OPTION_HANDLER (hw_option_handler);
109 static const OPTION hw_options[] =
111 { {"hw-info", no_argument, NULL, OPTION_HW_INFO },
112 '\0', NULL, "List configurable hw regions",
114 { {"info-hw", no_argument, NULL, OPTION_HW_INFO },
118 { {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE },
119 '\0', "on|off", "Trace all hardware devices",
121 { {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE },
125 { {"hw-device", required_argument, NULL, OPTION_HW_DEVICE },
126 '\0', "DEVICE", "Add the specified device",
129 { {"hw-list", no_argument, NULL, OPTION_HW_LIST },
130 '\0', NULL, "List the device tree",
133 { {"hw-file", required_argument, NULL, OPTION_HW_FILE },
134 '\0', "FILE", "Add the devices listed in the file",
137 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
142 /* Copied from ../ppc/psim.c:psim_merge_device_file() */
145 merge_device_file (struct sim_state *sd,
146 const char *file_name)
149 struct hw *current = STATE_HW (sd)->tree;
151 char device_path[1000];
153 /* try opening the file */
154 description = fopen (file_name, "r");
155 if (description == NULL)
162 while (fgets (device_path, sizeof(device_path), description))
165 /* check that a complete line was read */
166 if (strchr (device_path, '\n') == NULL)
168 fclose (description);
169 sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
172 *strchr (device_path, '\n') = '\0';
174 /* skip comments ("#" or ";") and blank lines lines */
175 for (device = device_path;
176 *device != '\0' && isspace (*device);
180 || device[0] == '\0')
182 /* merge any appended lines */
183 while (device_path[strlen (device_path) - 1] == '\\')
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,
193 fclose (description);
194 sim_io_eprintf (sd, "%s:%d: unexpected eof", file_name, line_nr);
197 if (strchr(device_path, '\n') == NULL)
200 sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr);
203 *strchr(device_path, '\n') = '\0';
206 /* parse this line */
207 current = hw_tree_parse (current, "%s", device);
209 fclose (description);
215 hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt,
216 char *arg, int is_command)
223 /* delay info until after the tree is finished */
224 STATE_HW (sd)->info_p = 1;
229 case OPTION_HW_TRACE:
233 STATE_HW (sd)->trace_p = 1;
235 else if (strcmp (arg, "yes") == 0
236 || strcmp (arg, "on") == 0)
238 STATE_HW (sd)->trace_p = 1;
240 else if (strcmp (arg, "no") == 0
241 || strcmp (arg, "off") == 0)
243 STATE_HW (sd)->trace_p = 0;
247 sim_io_eprintf (sd, "Option --hw-trace ignored\n");
248 /* set tracing on all devices */
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");
258 case OPTION_HW_DEVICE:
260 hw_tree_parse (STATE_HW (sd)->tree, "%s", arg);
266 sim_hw_print (sd, sim_io_vprintf);
272 return merge_device_file (sd, arg);
276 sim_io_eprintf (sd, "Unknown hw option %d\n", opt);
285 /* "hw" module install handler.
287 This is called via sim_module_install to install the "hw" subsystem
288 into the simulator. */
290 static MODULE_INIT_FN sim_hw_init;
291 static MODULE_UNINSTALL_FN sim_hw_uninstall;
294 sim_hw_install (struct sim_state *sd)
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");
307 sim_hw_init (struct sim_state *sd)
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);
316 /* Uninstall the "hw" subsystem from the simulator. */
319 sim_hw_uninstall (struct sim_state *sd)
321 /* hw_tree_delete (STATE_HW (sd)->tree); */
322 zfree (STATE_HW (sd));
323 STATE_HW (sd) = NULL;
328 /* Data transfers to/from the hardware device tree. There are several
332 /* CPU: The simulation is running and the current CPU/CIA
333 initiates a data transfer. */
336 sim_cpu_hw_io_read_buffer (sim_cpu *cpu,
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");
352 sim_cpu_hw_io_write_buffer (sim_cpu *cpu,
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");
370 /* SYSTEM: A data transfer is being initiated by the system. */
373 sim_hw_io_read_buffer (struct sim_state *sd,
380 STATE_HW (sd)->cpu = NULL;
381 return hw_io_read_buffer (hw, dest, space, addr, nr_bytes);
385 sim_hw_io_write_buffer (struct sim_state *sd,
392 STATE_HW (sd)->cpu = NULL;
393 return hw_io_write_buffer (hw, source, space, addr, nr_bytes);
398 /* Abort the simulation specifying HW as the reason */
401 hw_vabort (struct hw *me,
407 /* find an identity */
408 if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
410 else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
412 else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
413 name = hw_family (me);
416 /* construct an updated format string */
417 msg = alloca (strlen (name) + strlen (": ") + strlen (fmt) + 1);
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,
429 hw_abort (struct hw *me,
434 /* report the problem */
436 hw_vabort (me, fmt, ap);
441 sim_hw_abort (struct sim_state *sd,
449 sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap);
451 hw_vabort (me, fmt, ap);
456 /* MISC routines to tie HW into the rest of the system */
459 hw_halt (struct hw *me,
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);
469 hw_system_cpu (struct hw *me)
471 return STATE_HW (hw_system (me))->cpu;
475 hw_trace (struct hw *me,
479 if (hw_trace_p (me)) /* to be sure, to be sure */
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");
491 /* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */
494 do_hw_poll_read (struct hw *me,
495 do_hw_poll_read_method *read,
500 int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf);
503 else if (status == 0 && sizeof_buf == 0)
505 else if (status == 0)
507 else /* status < 0 */
510 if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN)
511 return HW_IO_NOT_READY;