sim-hw.c 11 KB

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