diff options
Diffstat (limited to 'sim/ppc/psim.c')
-rw-r--r-- | sim/ppc/psim.c | 283 |
1 files changed, 199 insertions, 84 deletions
diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c index 0c7024e..c2d3a60 100644 --- a/sim/ppc/psim.c +++ b/sim/ppc/psim.c @@ -26,6 +26,7 @@ #include "idecode.h" #include "options.h" +#include "tree.h" #include <stdio.h> #include <ctype.h> @@ -78,6 +79,7 @@ int current_environment; int current_alignment; int current_floating_point; int current_model_issue = MODEL_ISSUE_IGNORE; +int current_stdio = DO_USE_STDIO; model_enum current_model = WITH_DEFAULT_MODEL; @@ -87,16 +89,16 @@ INLINE_PSIM\ (device *) psim_tree(void) { - device *root = device_tree_add_parsed(NULL, "core"); - device_tree_add_parsed(root, "/aliases"); - device_tree_add_parsed(root, "/options"); - device_tree_add_parsed(root, "/chosen"); - device_tree_add_parsed(root, "/packages"); - device_tree_add_parsed(root, "/cpus"); - device_tree_add_parsed(root, "/openprom"); - device_tree_add_parsed(root, "/openprom/init"); - device_tree_add_parsed(root, "/openprom/trace"); - device_tree_add_parsed(root, "/openprom/options"); + device *root = tree_parse(NULL, "core"); + tree_parse(root, "/aliases"); + tree_parse(root, "/options"); + tree_parse(root, "/chosen"); + tree_parse(root, "/packages"); + tree_parse(root, "/cpus"); + tree_parse(root, "/openprom"); + tree_parse(root, "/openprom/init"); + tree_parse(root, "/openprom/trace"); + tree_parse(root, "/openprom/options"); return root; } @@ -122,55 +124,74 @@ psim_usage(int verbose) printf_filtered("\n"); printf_filtered("Where\n"); printf_filtered("\n"); - printf_filtered("\t<image> Name of the PowerPC program to run.\n"); + printf_filtered("\t<image> Name of the PowerPC program to run.\n"); if (verbose) { - printf_filtered("\t This can either be a PowerPC binary or\n"); - printf_filtered("\t a text file containing a device tree\n"); - printf_filtered("\t specification.\n"); - printf_filtered("\t PSIM will attempt to determine from the\n"); - printf_filtered("\t specified <image> the intended emulation\n"); - printf_filtered("\t environment.\n"); - printf_filtered("\t If PSIM gets it wrong, the emulation\n"); - printf_filtered("\t environment can be specified using the\n"); - printf_filtered("\t `-e' option (described below).\n"); + printf_filtered("\t This can either be a PowerPC binary or\n"); + printf_filtered("\t a text file containing a device tree\n"); + printf_filtered("\t specification.\n"); + printf_filtered("\t PSIM will attempt to determine from the\n"); + printf_filtered("\t specified <image> the intended emulation\n"); + printf_filtered("\t environment.\n"); + printf_filtered("\t If PSIM gets it wrong, the emulation\n"); + printf_filtered("\t environment can be specified using the\n"); + printf_filtered("\t `-e' option (described below).\n"); printf_filtered("\n"); } - printf_filtered("\t<image-arg> Argument to be passed to <image>\n"); + printf_filtered("\t<image-arg> Argument to be passed to <image>\n"); if (verbose) { - printf_filtered("\t These arguments will be passed to\n"); - printf_filtered("\t <image> (as standard C argv, argc)\n"); - printf_filtered("\t when <image> is started.\n"); + printf_filtered("\t These arguments will be passed to\n"); + printf_filtered("\t <image> (as standard C argv, argc)\n"); + printf_filtered("\t when <image> is started.\n"); printf_filtered("\n"); } - printf_filtered("\t<psim-option> See below\n"); + printf_filtered("\t<psim-option> See below\n"); printf_filtered("\n"); printf_filtered("The following are valid <psim-option>s:\n"); printf_filtered("\n"); - printf_filtered("\t-m <model> Specify the processor to model (604)\n"); - if (verbose) { - printf_filtered("\t Selects the processor to use when\n"); - printf_filtered("\t modeling execution units. Includes:\n"); - printf_filtered("\t 604, 603 and 603e\n"); - printf_filtered("\n"); } - printf_filtered("\t-e <os-emul> specify an OS or platform to model\n"); + + printf_filtered("\t-i Print instruction counting statistics\n"); + if (verbose) { printf_filtered("\n"); } + + printf_filtered("\t-I Print execution unit statistics\n"); + if (verbose) { printf_filtered("\n"); } + + printf_filtered("\t-e <os-emul> specify an OS or platform to model\n"); if (verbose) { - printf_filtered("\t Can be any of the following:\n"); - printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n"); - printf_filtered("\t netbsd - UEA + NetBSD system calls\n"); - printf_filtered("\t solaris - UEA + Solaris system calls\n"); - printf_filtered("\t linux - UEA + Linux system calls\n"); - printf_filtered("\t chirp - OEA + a few OpenBoot calls\n"); + printf_filtered("\t Can be any of the following:\n"); + printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n"); + printf_filtered("\t netbsd - UEA + NetBSD system calls\n"); + printf_filtered("\t solaris - UEA + Solaris system calls\n"); + printf_filtered("\t linux - UEA + Linux system calls\n"); + printf_filtered("\t chirp - OEA + a few OpenBoot calls\n"); printf_filtered("\n"); } - printf_filtered("\t-i Print instruction counting statistics\n"); - if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-I Print execution unit statistics\n"); + + printf_filtered("\t-f <file> Merge <file> into the device tree\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-r <size> Set RAM size in bytes (OEA environments)\n"); + + printf_filtered("\t-h -? -H give more detailed usage\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n"); + + printf_filtered("\t-m <model> Specify the processor to model (604)\n"); + if (verbose) { + printf_filtered("\t Selects the processor to use when\n"); + printf_filtered("\t modeling execution units. Includes:\n"); + printf_filtered("\t 604, 603 and 603e\n"); + printf_filtered("\n"); } + + printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n"); + if (verbose) { + printf_filtered("\t Specifies the number of processors that are\n"); + printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n"); + printf_filtered("\t simulation\n"); + printf_filtered("\n"); } + + printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-o <spec> add device <spec> to the device tree\n"); + + printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n"); if (verbose) { printf_filtered("\n"); } - printf_filtered("\t-h -? -H give more detailed usage\n"); + + printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n"); if (verbose) { printf_filtered("\n"); } + printf_filtered("\n"); trace_usage(verbose); device_usage(verbose); @@ -202,7 +223,11 @@ psim_options(device *root, break; case 'e': param = find_arg("Missing <emul> option for -e\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/os-emul %s", param); + tree_parse(root, "/openprom/options/os-emul %s", param); + break; + case 'f': + param = find_arg("Missing <file> option for -f\n", &argp, argv); + psim_merge_device_file(root, param); break; case 'h': case '?': @@ -212,45 +237,81 @@ psim_options(device *root, psim_usage(2); break; case 'i': - device_tree_add_parsed(root, "/openprom/trace/print-info 1"); + tree_parse(root, "/openprom/trace/print-info 1"); break; case 'I': - device_tree_add_parsed(root, "/openprom/trace/print-info 2"); - device_tree_add_parsed(root, "/openprom/options/model-issue %d", - MODEL_ISSUE_PROCESS); + tree_parse(root, "/openprom/trace/print-info 2"); + tree_parse(root, "/openprom/options/model-issue %d", + MODEL_ISSUE_PROCESS); break; case 'm': param = find_arg("Missing <model> option for -m\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/model \"%s", param); + tree_parse(root, "/openprom/options/model \"%s", param); + break; + case 'n': + param = find_arg("Missing <nr-smp> option for -n\n", &argp, argv); + tree_parse(root, "/openprom/options/smp %s", param); break; case 'o': - param = find_arg("Missing <device> option for -o\n", &argp, argv); - current = device_tree_add_parsed(current, "%s", param); + param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv); + current = tree_parse(current, "%s", param); break; case 'r': param = find_arg("Missing <ram-size> option for -r\n", &argp, argv); - device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx", - atol(param)); + tree_parse(root, "/openprom/options/oea-memory-size %s", + param); break; case 't': param = find_arg("Missing <trace> option for -t\n", &argp, argv); if (param[0] == '!') - device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1); + tree_parse(root, "/openprom/trace/%s 0", param+1); else - device_tree_add_parsed(root, "/openprom/trace/%s 1", param); + tree_parse(root, "/openprom/trace/%s 1", param); break; } p += 1; } argp += 1; } - /* force the trace node to (re)process its options */ - device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0); + /* force the trace node to process its options now *before* the tree + initialization occures */ + device_ioctl(tree_find_device(root, "/openprom/trace"), + NULL, 0, + device_ioctl_set_trace); /* return where the options end */ return argv + argp; } +INLINE_PSIM\ +(void) +psim_command(device *root, + char **argv) +{ + int argp = 0; + if (argv[argp] == NULL) { + return; + } + else if (strcmp(argv[argp], "trace") == 0) { + const char *opt = find_arg("Missing <trace> option", &argp, argv); + if (opt[0] == '!') + trace_option(opt + 1, 0); + else + trace_option(opt, 1); + } + else if (strcmp(*argv, "change-media") == 0) { + char *device = find_arg("Missing device name", &argp, argv); + char *media = argv[++argp]; + device_ioctl(tree_find_device(root, device), NULL, 0, + device_ioctl_change_media, media); + } + else { + printf_filtered("Unknown PSIM command %s, try\n", argv[argp]); + printf_filtered(" trace <trace-option>\n"); + printf_filtered(" change-media <device> [ <new-image> ]\n"); + } +} + /* create the simulator proper from the device tree and executable */ @@ -274,13 +335,13 @@ psim_create(const char *file_name, error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name); /* fill in the missing real number of CPU's */ - nr_cpus = device_find_integer_property(root, "/openprom/options/smp"); + nr_cpus = tree_find_integer_property(root, "/openprom/options/smp"); if (MAX_NR_PROCESSORS < nr_cpus) error("target and configured number of cpus conflict\n"); /* fill in the missing TARGET BYTE ORDER information */ current_target_byte_order - = (device_find_boolean_property(root, "/options/little-endian?") + = (tree_find_boolean_property(root, "/options/little-endian?") ? LITTLE_ENDIAN : BIG_ENDIAN); if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order) @@ -295,7 +356,7 @@ psim_create(const char *file_name, error("host and configured byte order conflict\n"); /* fill in the missing OEA/VEA information */ - env = device_find_string_property(root, "/openprom/options/env"); + env = tree_find_string_property(root, "/openprom/options/env"); current_environment = ((strcmp(env, "user") == 0 || strcmp(env, "uea") == 0) ? USER_ENVIRONMENT @@ -313,7 +374,7 @@ psim_create(const char *file_name, /* fill in the missing ALLIGNMENT information */ current_alignment - = (device_find_boolean_property(root, "/openprom/options/strict-alignment?") + = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?") ? STRICT_ALIGNMENT : NONSTRICT_ALIGNMENT); if (CURRENT_ALIGNMENT != current_alignment) @@ -321,15 +382,23 @@ psim_create(const char *file_name, /* fill in the missing FLOATING POINT information */ current_floating_point - = (device_find_boolean_property(root, "/openprom/options/floating-point?") + = (tree_find_boolean_property(root, "/openprom/options/floating-point?") ? HARD_FLOATING_POINT : SOFT_FLOATING_POINT); if (CURRENT_FLOATING_POINT != current_floating_point) error("target and configured floating-point conflict\n"); + /* fill in the missing STDIO information */ + current_stdio + = (tree_find_boolean_property(root, "/openprom/options/use-stdio?") + ? DO_USE_STDIO + : DONT_USE_STDIO); + if (CURRENT_STDIO != current_stdio) + error("target and configured stdio interface conflict\n"); + /* sort out the level of detail for issue modeling */ current_model_issue - = device_find_integer_property(root, "/openprom/options/model-issue"); + = tree_find_integer_property(root, "/openprom/options/model-issue"); if (CURRENT_MODEL_ISSUE != current_model_issue) error("target and configured model-issue conflict\n"); @@ -341,7 +410,7 @@ psim_create(const char *file_name, ihandle into the corresponding cpu's phandle and then querying the "name" property, the cpu type can be determined. Ok? */ - model_set(device_find_string_property(root, "/openprom/options/model")); + model_set(tree_find_string_property(root, "/openprom/options/model")); /* create things */ system = ZALLOC(psim); @@ -364,7 +433,7 @@ psim_create(const char *file_name, /* dump out the contents of the device tree */ if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree]) - device_tree_traverse(root, device_tree_print_device, NULL, NULL); + tree_print(root); if (ppc_trace[trace_dump_device_tree]) error(""); @@ -419,6 +488,7 @@ psim_halt(psim *system, longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1); } + INLINE_PSIM\ (int) psim_last_cpu(psim *system) @@ -458,7 +528,7 @@ INLINE_PSIM\ psim_device(psim *system, const char *path) { - return device_tree_find_device(system->devices, path); + return tree_find_device(system->devices, path); } INLINE_PSIM\ @@ -487,19 +557,20 @@ psim_init(psim *system) cpu_init(system->processors[cpu_nr]); /* init all the devices (which updates the cpus) */ - device_tree_init(system->devices, system); + tree_init(system->devices, system); /* and the emulation (which needs an initialized device tree) */ os_emul_init(system->os_emulation, system->nr_cpus); /* now sync each cpu against the initialized state of its registers */ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) { - cpu_synchronize_context(system->processors[cpu_nr]); - cpu_page_tlb_invalidate_all(system->processors[cpu_nr]); + cpu *processor = system->processors[cpu_nr]; + cpu_synchronize_context(processor, cpu_get_program_counter(processor)); + cpu_page_tlb_invalidate_all(processor); } - /* force loop to restart */ - system->last_cpu = -1; /* when incremented will become 0 - first CPU */ + /* force loop to start with first cpu (after processing events) */ + system->last_cpu = system->nr_cpus - 1; } INLINE_PSIM\ @@ -510,14 +581,15 @@ psim_stack(psim *system, { /* pass the stack device the argv/envp and let it work out what to do with it */ - device *stack_device = device_tree_find_device(system->devices, - "/openprom/init/stack"); + device *stack_device = tree_find_device(system->devices, + "/openprom/init/stack"); if (stack_device != (device*)0) { unsigned_word stack_pointer; psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer); device_ioctl(stack_device, NULL, /*cpu*/ 0, /*cia*/ + device_ioctl_create_stack, stack_pointer, argv, envp); @@ -778,7 +850,8 @@ psim_read_memory(psim *system, error("psim_read_memory() invalid cpu\n"); processor = system->processors[which_cpu]; return vm_data_map_read_buffer(cpu_data_map(processor), - buffer, vaddr, nr_bytes); + buffer, vaddr, nr_bytes, + NULL, -1); } @@ -798,7 +871,8 @@ psim_write_memory(psim *system, error("psim_read_memory() invalid cpu\n"); processor = system->processors[which_cpu]; return vm_data_map_write_buffer(cpu_data_map(processor), - buffer, vaddr, nr_bytes, 1); + buffer, vaddr, nr_bytes, 1/*violate-read-only*/, + NULL, -1); } @@ -818,20 +892,61 @@ INLINE_PSIM\ psim_merge_device_file(device *root, const char *file_name) { - FILE *description = fopen(file_name, "r"); - int line_nr = 0; + FILE *description; + int line_nr; char device_path[1000]; - device *current = root; + device *current; + + /* try opening the file */ + description = fopen(file_name, "r"); + if (description == NULL) { + perror(file_name); + error("Invalid file %s specified", file_name); + } + + line_nr = 0; + current = root; while (fgets(device_path, sizeof(device_path), description)) { - /* check all of line was read */ + char *device; + /* check that the full line was read */ if (strchr(device_path, '\n') == NULL) { fclose(description); - error("create_filed_device_tree() line %d to long: %s\n", - line_nr, device_path); + error("%s:%d: line to long - %s", + file_name, line_nr, device_path); } + else + *strchr(device_path, '\n') = '\0'; line_nr++; + /* skip comments ("#" or ";") and blank lines lines */ + for (device = device_path; + *device != '\0' && isspace(*device); + device++); + if (device[0] == '#' + || device[0] == ';' + || device[0] == '\0') + continue; + /* merge any appended lines */ + while (device_path[strlen(device_path) - 1] == '\\') { + int curlen = strlen(device_path) - 1; + /* zap \ */ + device_path[curlen] = '\0'; + /* append the next line */ + if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) { + fclose(description); + error("%s:%s: unexpected eof in line continuation - %s", + file_name, line_nr, device_path); + } + if (strchr(device_path, '\n') == NULL) { + fclose(description); + error("%s:%d: line to long - %s", + file_name, line_nr, device_path); + } + else + *strchr(device_path, '\n') = '\0'; + line_nr++; + } /* parse this line */ - current = device_tree_add_parsed(current, "%s", device_path); + current = tree_parse(current, "%s", device); } fclose(description); } |