diff --git a/CMakeLists.txt b/CMakeLists.txt index a715f9a6..beeda95d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,9 +202,6 @@ option(WITH_TAP option(WITH_VIDEO "Enable (=1)/disable (=0) simulator display and graphics support (def: enabled)" TRUE) -option(PANDA_LIGHTS - "Enable (=1)/disable (=0) KA-10/KI-11 simulator's Panda display. (def: disabled)" - FALSE) option(DONT_USE_ROMS "Enable (=1)/disable (=0) building support ROMs. (def: disabled)" FALSE) diff --git a/PDP10/CMakeLists.txt b/PDP10/CMakeLists.txt index c8b68033..20d60dde 100644 --- a/PDP10/CMakeLists.txt +++ b/PDP10/CMakeLists.txt @@ -46,6 +46,20 @@ add_simulator(pdp10 NO_INSTALL TEST pdp10) + +option(PANDA_LIGHTS + "Enable (=1)/disable (=0) KA-10/KI-11 simulator's Panda display. (def: disabled)" + FALSE) +option(PIDP10 + "Enable (=1)/disable (=0) PIDP10 display options (def: disabled)" + FALSE) + +### Ensure that the options are mutually exclusive: +if (PANDA_LIGHTS AND PIDP10) + message(FATAL_ERROR "PANDA_LIGHTS and PIDP10 options are mutually exclusive. Choose one.") +endif () + + add_simulator(pdp10-ka SOURCES ${KA10D}/kx10_cpu.c @@ -103,10 +117,14 @@ add_simulator(pdp10-ka TEST ka10) if (PANDA_LIGHTS) - target_sources(pdp10-ka PUBLIC ${PDP10D}/ka10_lights.c) + target_sources(pdp10-ka PUBLIC ${PDP10D}/kx10_lights.c) target_compile_definitions(pdp10-ka PUBLIC PANDA_LIGHTS) target_link_libraries(pdp10-ka PUBLIC usb-1.0) -endif (PANDA_LIGHTS) +endif () +if (PIDP10) + target_sources(pdp10-ka PUBLIC ${PDP10D}/ka10_pipanel.c) + target_compile_definitions(pdp10-ka PUBLIC PIDP10=1) +endif () add_simulator(pdp10-ki SOURCES diff --git a/README-CMake.md b/README-CMake.md index 406a3db5..eacf2dae 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -1288,6 +1288,13 @@ add_simulator(simulator_name ## in its sim_instr() instruction simulation loop: USES_AIO + ## Arguments to append after "RegisterSanityCheck". These arguments + ## appear between "RegisterSanityCheck" and the test script, if + ## given, e.g.: + ## + ## mysimulator RegisterSanityCheck -r -t path/to/mysim_test.ini + TEST_ARGS "-r" + ## Packaging "family" (group) to which the simulator belongs, ## for packagers that support grouping (Windows: NSIS .exe, ## WIX .msi; macOS) @@ -1386,9 +1393,19 @@ solution is `cmake/generate.py` to update the affected simulator ```sh ## You have to be in the cmake subdirectory to run the generate.py script $ cd cmake +$ python -m generate --help +usage: generate.py [-h] [--debug [DEBUG]] [--srcdir SRCDIR] [--orphans] + +SIMH simulator CMakeLists.txt generator. + +options: + -h, --help show this help message and exit + --debug [DEBUG] Debug level (0-3, 0 == off) + --srcdir SRCDIR makefile source directory. + --orphans Check for packaging orphans + # [simh_source] is the absolute path to your top-level SIMH source directory -$ python -m generate -generate.py: Expecting to emit 77 simulators. +$ python -m generate --orphans generate.py: Looking for makefile, starting in [simh-source]/open-simh/cmake generate.py: Looking for makefile, trying [simh-source]/open-simh generate.py: Processing [simh-source]/open-simh/makefile @@ -1423,6 +1440,7 @@ generate.py: all target vaxstation4000m60 generate.py: all target microvax3100m80 generate.py: all target vaxstation4000vlc generate.py: all target infoserver1000 +generate.py: all target nd100 generate.py: all target nova generate.py: all target eclipse generate.py: all target hp2100 @@ -1475,6 +1493,7 @@ generate.py: all target sel32 generate.py: exp target alpha generate.py: exp target pdq3 generate.py: exp target sage +generate.py: Expecting to emit 78 simulators. ==== writing to [simh-source]/open-simh/3B2/CMakeLists.txt ==== writing to [simh-source]/open-simh/ALTAIR/CMakeLists.txt ==== writing to [simh-source]/open-simh/AltairZ80/CMakeLists.txt @@ -1495,6 +1514,7 @@ generate.py: exp target sage ==== writing to [simh-source]/open-simh/Intel-Systems/scelbi/CMakeLists.txt ==== writing to [simh-source]/open-simh/Interdata/CMakeLists.txt ==== writing to [simh-source]/open-simh/LGP/CMakeLists.txt +==== writing to [simh-source]/open-simh/ND100/CMakeLists.txt ==== writing to [simh-source]/open-simh/NOVA/CMakeLists.txt ==== writing to [simh-source]/open-simh/PDP1/CMakeLists.txt ==== writing to [simh-source]/open-simh/PDP10/CMakeLists.txt diff --git a/cmake/CMake-Maintainers.md b/cmake/CMake-Maintainers.md index ce44d196..927f1beb 100644 --- a/cmake/CMake-Maintainers.md +++ b/cmake/CMake-Maintainers.md @@ -17,6 +17,8 @@ - [`dep-locate.cmake`, `dep-link.cmake`: Dependency libraries](#dep-locatecmake-dep-linkcmake-dependency-libraries) - [`simh-simulators.cmake`](#simh-simulatorscmake) - [`generate.py`: Automagic `makefile` → CMake infrastructure](#generatepy-automagic-makefile--cmake-infrastructure) + - [`generate.py` Internals](#generatepy-internals) + - [Using `generate.py` outside of *open-simh*](#using-generatepy-outside-of-open-simh) - [CPack configuration](#cpack-configuration) <!-- markdown-toc end --> @@ -468,33 +470,47 @@ case in the future. The SIMH `makefile` is still considered the authoritative source for simulator compiler command lines and source code. `generate.py` was built to scrape the `makefile`'s `all` and `exp` rules, gather simulator source code lists, simulator-specific defines, and emit the simulator subdirectory `CMakeLists.txt` and -the `simh-simulators.cmake` files. To synchronize the SIMH *CMake* infrastructure with the SIMH -`makefile` when new simulators are added to the `makefile`, when compiler command lines change or new -simulator source code is added: +the `simh-simulators.cmake` files. + +To synchronize the *CMake* infrastructure with the `makefile` when new simulators are added to the +`makefile`, when compiler command lines change or new simulator source code is added: ``` shell -$ cd cmake; python3 -m generate +$ (cd cmake; python3 -m generate) + +## Alternatively: + +$ python3 cmake/generate.py ``` -Internally, `generate.py` has three principal classes defined in the `cmake/simgen` subdirectory: -`CMakeBuildSystem` (`cmake_container.py`), `SimCollection` (`sim_collection.py`) and `SIMHBasicSimulator` -(`basic_simulator.py`). +Note that `generate.py` ensures that it has collected all of the `makefile`-s simulators by cross-referencing +the simulators enumerated in the `cmake/simgen/packaging.py` script to the collected simulators scraped from +the `makefile`. When the expected simulators do not match the `generate.py`-collected simulator list, +`generate.py` will list the missing simulators and exit. If you are maintaining a separate simulator source +repository, please customize your `cmake/simgen/packaging.py` script to reflect the expected simulators in +your source tree. -- `CMakeBuildSystem`: The top-level container for the entire SIMH simulator collection scraped from the - `makefile`. It's a container that maps a `SimCollection` simulator group to a subdirectory. The - `CMakeBuildSystem.extract` method interprets the `makefile`'s parsed contents, and builds up the + +#### `generate.py` Internals + +`generate.py` has three principal classes defined in the `cmake/simgen` subdirectory: `CMakeBuildSystem`, +`SimCollection` and `SIMHBasicSimulator`. + +- `CMakeBuildSystem` (`cmake_container.py`): The top-level container for the entire SIMH simulator collection + scraped from the `makefile`. It's a container that maps a `SimCollection` simulator group to a subdirectory. + The `CMakeBuildSystem.extract` method interprets the `makefile`'s parsed contents, and builds up the per-subdirectory `SimCollection` simulator groups. -- `SimCollection`: A group of simulators, e.g., all of the VAX or PDP-11 simulators, or the PDP-8 - simulator. It also maps simulator source macro names to source lists that become *CMake* variables to - make the emitted `CMakeLists.txt` files more readable. The `SimCollection.write_simulators` method emits - the simulator subdirectory `CMakeLists.txt` file. +- `SimCollection` (`sim_collection.py`): A group of simulators, e.g., all of the VAX or PDP-11 simulators, + or the PDP-8 simulator. It also maps simulator source macro names to source lists that become *CMake* + variables to make the emitted `CMakeLists.txt` files more readable. The `SimCollection.write_simulators` + method emits the simulator subdirectory `CMakeLists.txt` file. -- `SIMHBasicSimulator`: An individual SIMH simulator stored inside a `SimCollection`. This class keeps - track of the simulator's sources, simulator-specific defines and include paths, as well as detects when - the simulator requires 64-bit address and 64-bit data, when the simulator requires video support. The - `SIMHBasicSimulator.write_section` method emits the individual simulator's `add_simulator` function call - to the `CMakeLists.txt` file stream passed by the parent `SimCollection`. +- `SIMHBasicSimulator` (`basic_simulator.py`): An individual SIMH simulator stored inside a `SimCollection`. + This class tracks of the simulator's sources, simulator-specific defines and include paths, as well as + detects when the simulator requires 64-bit address and 64-bit data, when the simulator requires video + support. The `SIMHBasicSimulator.write_section` method emits the individual simulator's `add_simulator` + function call to the `CMakeLists.txt` file stream passed by the parent `SimCollection`. `SIMHBasicSimulator` has several subclasses that specialize the `write_section` method. For example, the *BESM6* simulator requires a Cyrillic font, which requires additional *CMake* code to search for an @@ -504,6 +520,118 @@ Internally, `generate.py` has three principal classes defined in the `cmake/simg subclasses. If the simulator's name is not present in the `special_simulators` dictionary, `SIMHBasicSimulator` is used. +#### Using `generate.py` outside of *open-simh* + +`generate.py` can be used outside of the *open-simh* project for separately maintained simulator +repositories. If you do use `generate.py` in your own simulator repository, you **must** customize +the `simgen/packaging.py` script so that the expected simulators matches the collected simulators. + +An example `packaging.py` script that can be copied, pasted and customized (leave the boilerplate +in place, edit and customize after the "Your customizations here...") + +```python +### packaging.py boilerplate starts: + +import os +import functools + +## Initialize package_info to an empty dictionary here so +## that it's visible to write_packaging(). +package_info = {} + + +class SIMHPackaging: + def __init__(self, family, install_flag = True) -> None: + self.family = family + self.processed = False + self.install_flag = install_flag + + def was_processed(self) -> bool: + return self.processed == True + + def encountered(self) -> None: + self.processed = True + +class PkgFamily: + def __init__(self, component_name, display_name, description) -> None: + self.component_name = component_name + self.display_name = display_name + self.description = description + + def write_component_info(self, stream, indent) -> None: + pkg_description = self.description + if pkg_description[-1] != '.': + pkg_description += '.' + sims = [] + for sim, pkg in package_info.items(): + if pkg.family is self and pkg.was_processed(): + sims.append(sim) + sims.sort() + + if len(sims) > 0: + sims.sort() + pkg_description += " Simulators: " + ', '.join(sims) + indent0 = ' ' * indent + indent4 = ' ' * (indent + 4) + stream.write(indent0 + "cpack_add_component(" + self.component_name + "\n") + stream.write(indent4 + "DISPLAY_NAME \"" + self.display_name + "\"\n") + stream.write(indent4 + "DESCRIPTION \"" + pkg_description + "\"\n") + stream.write(indent0 + ")\n") + + def __lt__(self, obj): + return self.component_name < obj.component_name + def __eq__(self, obj): + return self.component_name == obj.component_name + def __gt__(self, obj): + return self.component_name > obj.component_name + def __hash__(self): + return hash(self.component_name) + +def write_packaging(toplevel_dir) -> None: + families = set([sim.family for sim in package_info.values()]) + pkging_file = os.path.join(toplevel_dir, 'cmake', 'simh-packaging.cmake') + print("==== writing {0}".format(pkging_file)) + with open(pkging_file, "w") as stream: + ## Runtime support family: + stream.write("""## The default runtime support component/family: +cpack_add_component(runtime_support + DISPLAY_NAME "Runtime support" + DESCRIPTION "Required SIMH runtime support (documentation, shared libraries)" + REQUIRED +) + +## Basic documentation for SIMH +install(FILES doc/simh.doc TYPE DOC COMPONENT runtime_support) + +""") + + ## Simulators: + for family in sorted(families): + family.write_component_info(stream, 0) + +## The default packaging family for simulators not associated with +## any particular family. Also used for runtime and documentation: +default_family = PkgFamily("default_family", "Default SIMH simulator family.", + """The SIMH simulator collection of historical processors and computing systems that do not belong to +any other simulated system family""" +) + +### packaging.py boilerplate ends... + +### Your customizations here: + +### Instantiate a simulator package family: +foosim_family = PkgFamily("foosim_family", "A collection of simulators", + """Description of your simulators, may span multiple lines within the three quote +marks.""" +) + +### Add simulators to the package famil(y|ies) +package_info["sim1"] = SIMHPackaging(foosim_family) +package_info["sim2"] = SIMHPackaging(foosim_family) +``` + + ### CPack configuration [*CPack*][cpack] is the *CMake* utility for packaging SIMH's pre-built binaries. Like *CMake*, *CPack* has diff --git a/cmake/add_simulator.cmake b/cmake/add_simulator.cmake index d56ccd19..e87ef16c 100644 --- a/cmake/add_simulator.cmake +++ b/cmake/add_simulator.cmake @@ -171,10 +171,13 @@ list(APPEND ADD_SIMULATOR_1ARG ## DEFINES: List of extra command line manifest constants ("-D" items) ## INCLUDES: List of extra include directories ## SOURCES: List of source files +## TEST_ARGS: Additional arguments to append to the command line after +## "RegisterSanityCheck" list(APPEND ADD_SIMULATOR_NARG "DEFINES" "INCLUDES" "SOURCES" + "TEST_ARGS" ) function (simh_executable_template _targ) @@ -281,6 +284,9 @@ function (add_simulator _targ) ## Simulator-specific tests: list(APPEND test_cmd "${_targ}" "RegisterSanityCheck") + if (SIMH_TEST_ARGS) + list(APPEND test_cmd ${SIMH_TEST_ARGS}) + endif () if (DEFINED SIMH_TEST) string(APPEND test_fname ${CMAKE_CURRENT_SOURCE_DIR} "/tests/${SIMH_TEST}_test.ini") diff --git a/cmake/generate.py b/cmake/generate.py index c1993645..50e1def0 100644 --- a/cmake/generate.py +++ b/cmake/generate.py @@ -32,9 +32,9 @@ def process_makefile(makefile_dir, debug=0): if debug >= 4: pprint.pp(defs) - all_rule = rules.get('all') + all_rule = rules.get('all') or rules.get('ALL') if all_rule is None: - print('{0}: "all" rule not found. Cannot process.'.format(GEN_SCRIPT_NAME)) + print('{0}: "all" rule not found. Cannot proceed.'.format(GEN_SCRIPT_NAME)) simulators = SCC.CMakeBuildSystem() for all_targ in SPM.shallow_expand_vars(all_rule, defs).split(): @@ -42,9 +42,10 @@ def process_makefile(makefile_dir, debug=0): walk_target_deps(all_targ, defs, rules, actions, simulators, debug=debug) experimental_rule = rules.get('experimental') - for experimental_targ in SPM.shallow_expand_vars(experimental_rule, defs).split(): - print("{0}: exp target {1}".format(GEN_SCRIPT_NAME, experimental_targ)) - walk_target_deps(experimental_targ, defs, rules, actions, simulators, debug=debug) + if experimental_rule is not None: + for experimental_targ in SPM.shallow_expand_vars(experimental_rule, defs).split(): + print("{0}: exp target {1}".format(GEN_SCRIPT_NAME, experimental_targ)) + walk_target_deps(experimental_targ, defs, rules, actions, simulators, debug=debug) simulators.collect_vars(defs, debug=debug) return simulators @@ -70,6 +71,8 @@ def walk_target_deps(target, defs, rules, actions, simulators, depth='', debug=0 print('{0}-- target: {1}'.format(depth, target)) target_deps = SPM.target_dep_list(target, rules, defs) + if debug >= 2: + print('{0}target deps: {1}'.format(depth, target_deps)) has_buildrom = any(filter(lambda dep: dep == '${BUILD_ROMS}', target_deps)) if debug >= 1: @@ -131,15 +134,14 @@ if __name__ == '__main__': help='Debug level (0-3, 0 == off)') args.add_argument('--srcdir', default=None, help='makefile source directory.') - ## args.add_argument('--file', '-f', default=os.path.join(GEN_SCRIPT_DIR, 'simh_makefile.cmake'), - ## help='Output file for "all-in-one" CMakeLists.txt, default is simh_makefile.cmake') + args.add_argument('--skip-orphans', action='store_true', + help='Skip the check for packaging orphans') + flags = vars(args.parse_args()) debug_level = flags.get('debug') makefile_dir = flags.get('srcdir') - print('{0}: Expecting to emit {1} simulators.'.format(GEN_SCRIPT_NAME, len(SPKG.package_info.keys()))) - found_makefile = True if makefile_dir is None: ## Find the makefile, which should be one directory up from this Python @@ -171,15 +173,22 @@ if __name__ == '__main__': ## Sanity check: Make sure that all of the simulators in SPKG.package_info have ## been encountered for simdir in sims.dirs.keys(): + if debug_level >= 2: + print('{}: simdir {}'.format(GEN_SCRIPT_NAME, simdir)) for sim in sims.dirs[simdir].simulators.keys(): SPKG.package_info[sim].encountered() - orphans = [ sim for sim, pkg_info in SPKG.package_info.items() if not pkg_info.was_processed() ] - if len(orphans) > 0: - print('{0}: Simulators not extracted from makefile:'.format(GEN_SCRIPT_NAME)) - for orphan in orphans: - print('{0}{1}'.format(' ' * 4, orphan)) - sys.exit(1) + if not flags.get('skip_orphans'): + print('{0}: Expecting to emit {1} simulators.'.format(GEN_SCRIPT_NAME, len(SPKG.package_info.keys()))) + + orphans = [ sim for sim, pkg_info in SPKG.package_info.items() if not pkg_info.was_processed() ] + if len(orphans) > 0: + print('{0}: Simulators not extracted from makefile:'.format(GEN_SCRIPT_NAME)) + for orphan in orphans: + print('{0}{1}'.format(' ' * 4, orphan)) + sys.exit(1) + else: + print('{0}: All simulators present and accounted for!'.format(GEN_SCRIPT_NAME)) if debug_level >= 1: pp = pprint.PrettyPrinter() diff --git a/cmake/simgen/basic_simulator.py b/cmake/simgen/basic_simulator.py index 4959ada9..9d3eb9d6 100644 --- a/cmake/simgen/basic_simulator.py +++ b/cmake/simgen/basic_simulator.py @@ -7,8 +7,9 @@ import simgen.packaging as SPKG class SIMHBasicSimulator: """ """ - def __init__(self, sim_name, dir_macro, test_name, buildrom): + def __init__(self, sim_name, dir_macro, test_name, buildrom, test_args=None): self.sim_name = sim_name + ## self.dir_macro -> Directory macro (e.g., "${PDP11D}" for source self.dir_macro = dir_macro self.test_name = test_name self.int64 = False @@ -22,6 +23,11 @@ class SIMHBasicSimulator: self.besm6_sdl_hack = False ## self.uses_aio -> True if the simulator uses AIO self.uses_aio = False + ## self.test_args -> Simulator flags to pass to the test phase. Used by ibm1130 to + ## pass "-g" to disable to the GUI. This argument can be a single + ## string or a list. + self.test_args = test_args + self.sources = [] self.defines = [] self.includes = [] @@ -128,6 +134,13 @@ class SIMHBasicSimulator: stream.write('\n' + indent4 + "BESM6_SDL_HACK") if self.uses_aio: stream.write('\n' + indent4 + "USES_AIO") + if self.test_args: + out_args = self.test_args + if isinstance(self.test_args, str): + out_args = self.test_args.split() + + out_args = ' '.join('"{0}"'.format(w) for w in out_args) + stream.write('\n' + indent4 + 'TEST_ARGS {}'.format(out_args)) if self.buildrom: stream.write('\n' + indent4 + "BUILDROMS") stream.write('\n' + indent4 + "LABEL " + test_label) @@ -250,22 +263,6 @@ class BESM6Simulator(SIMHBasicSimulator): 'unset(cand_fonts)', 'unset(cand_fontdirs)\n'])) -class KA10Simulator(SIMHBasicSimulator): - def __init__(self, sim_name, dir_macro, test_name, buildrom): - super().__init__(sim_name, dir_macro, test_name, buildrom) - - def write_simulator(self, stream, indent, test_label='ka10'): - super().write_simulator(stream, indent, test_label) - stream.write('\n') - stream.write('\n'.join([ - 'if (PANDA_LIGHTS)', - ' target_sources({0} PUBLIC {1}/ka10_lights.c)'.format(self.sim_name, self.dir_macro), - ' target_compile_definitions({0} PUBLIC PANDA_LIGHTS)'.format(self.sim_name), - ' target_link_libraries({0} PUBLIC usb-1.0)'.format(self.sim_name), - 'endif (PANDA_LIGHTS)' - ])) - stream.write('\n') - class IBM650Simulator(SIMHBasicSimulator): '''The IBM650 simulator creates relatively deep stacks, which will fail on Windows. Adjust target simulator link flags to provide a 8M stack, similar to Linux. @@ -293,25 +290,6 @@ class IBM650Simulator(SIMHBasicSimulator): 'endif()' ])) -class IBM1130Simulator(SIMHBasicSimulator): - '''The IBM650 simulator creates relatively deep stacks, which will fail on Windows. - Adjust target simulator link flags to provide a 8M stack, similar to Linux. - ''' - def __init__(self, sim_name, dir_macro, test_name, buildrom): - super().__init__(sim_name, dir_macro, test_name, buildrom) - - def write_simulator(self, stream, indent, test_label='ibm650'): - super().write_simulator(stream, indent, test_label) - stream.write('\n'.join([ - '', - 'if (WIN32)', - ' target_compile_definitions(ibm1130 PRIVATE GUI_SUPPORT)', - ' ## missing source in IBM1130?' - ' ## target_sources(ibm1130 PRIVATE ibm1130.c)', - 'endif()' - ])) - - if '_dispatch' in pprint.PrettyPrinter.__dict__: def sim_pprinter(pprinter, sim, stream, indent, allowance, context, level): cls = sim.__class__ diff --git a/cmake/simgen/ibm1130_simulator.py b/cmake/simgen/ibm1130_simulator.py new file mode 100644 index 00000000..84ef1d9f --- /dev/null +++ b/cmake/simgen/ibm1130_simulator.py @@ -0,0 +1,30 @@ +## IBM 1130 simulator customizations: +## +## - Add the Win32 resource file for Windows builds +## - Add the "-g" test flag to bypass/disable the simulator GUI when +## running RegisterSanityCheck test. +import simgen.basic_simulator as SBS + +class IBM1130Simulator(SBS.SIMHBasicSimulator): + '''The IBM650 simulator creates relatively deep stacks, which will fail on Windows. + Adjust target simulator link flags to provide a 8M stack, similar to Linux. + ''' + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom, test_args="-g") + + def write_simulator(self, stream, indent, test_label='ibm650'): + super().write_simulator(stream, indent, test_label) + stream.write('\n'.join([ + '', + 'if (WIN32)', + ' ## Add GUI support, compile in resources:', + ' target_compile_definitions(ibm1130 PRIVATE GUI_SUPPORT)', + ' target_sources(ibm1130 PRIVATE ibm1130.rc)', + 'endif()', + '', + '# IBM 1130 utilities:', + '# add_subdirectory(utils)', + '' + ])) + + diff --git a/cmake/simgen/packaging.py b/cmake/simgen/packaging.py index 6f088a2c..220eaa5f 100644 --- a/cmake/simgen/packaging.py +++ b/cmake/simgen/packaging.py @@ -30,16 +30,18 @@ class PkgFamily: pkg_description += '.' sims = [] for sim, pkg in package_info.items(): - if pkg.family is self: + if pkg.family is self and pkg.was_processed(): sims.append(sim) - sims.sort() - pkg_description += " Simulators: " + ', '.join(sims) - indent0 = ' ' * indent - indent4 = ' ' * (indent + 4) - stream.write(indent0 + "cpack_add_component(" + self.component_name + "\n") - stream.write(indent4 + "DISPLAY_NAME \"" + self.display_name + "\"\n") - stream.write(indent4 + "DESCRIPTION \"" + pkg_description + "\"\n") - stream.write(indent0 + ")\n") + + if len(sims) > 0: + sims.sort() + pkg_description += " Simulators: " + ', '.join(sims) + indent0 = ' ' * indent + indent4 = ' ' * (indent + 4) + stream.write(indent0 + "cpack_add_component(" + self.component_name + "\n") + stream.write(indent4 + "DISPLAY_NAME \"" + self.display_name + "\"\n") + stream.write(indent4 + "DESCRIPTION \"" + pkg_description + "\"\n") + stream.write(indent0 + ")\n") def __lt__(self, obj): return self.component_name < obj.component_name diff --git a/cmake/simgen/parse_makefile.py b/cmake/simgen/parse_makefile.py index 73f98f58..eb11c2f3 100644 --- a/cmake/simgen/parse_makefile.py +++ b/cmake/simgen/parse_makefile.py @@ -13,9 +13,10 @@ _variable_rx = re.compile(r"\s*([A-Za-z][\w_-]+)\s*=\s*(.*)") _rule_rx = re.compile(r"(((\$[({])*\w[\w_-]+[)}]*)+)\s*:\s*(.*)") # Regex that recognizes variables. Group 1 is the variable's name. -_var_rx = re.compile(r"^\$[{(]([A-Za-z][\w_-]*)[)}]$") -_var_rx2 = re.compile(r"\$[{(]([A-Za-z][\w_-]*)[)}]") -_norm_var_rx = re.compile(r"\$\(([A-Za-z][\w_-]*)\)") +_var_pattern = r"[A-Za-z][\w_-]*" +_var_rx = re.compile(r"^\$[{(](" + _var_pattern + r")[)}]$") +_var_rx2 = re.compile(r"\$[{(](" + _var_pattern + r")[)}]") +_norm_var_rx = re.compile(r"\$[(](" + _var_pattern + r")[)]") def parse_makefile(fn, g_vars=None, g_rules=None, g_actions=None): """Parse a Makefile-style file. @@ -56,8 +57,15 @@ def parse_makefile(fn, g_vars=None, g_rules=None, g_actions=None): line = fp.readline() elif rmatch: + ## make allows "$(VAR)" and "${VAR}" to be used interchangably, so there's a + ## possibility that the sim developer used both forms in the target, e.g.: + ## + ## foosim: $(BIN)foosim$(EXE) + ## + ## ${BIN}foosim${EXE}: stuff that foosim depends on... + n, v = rmatch.group(1, 4) - rules[n] = v + rules[normalize_variables(n)] = normalize_variables(v) ## Collect the actions: collected = [] diff --git a/cmake/simgen/pdp10_simulator.py b/cmake/simgen/pdp10_simulator.py new file mode 100644 index 00000000..3a8ebf73 --- /dev/null +++ b/cmake/simgen/pdp10_simulator.py @@ -0,0 +1,45 @@ +## KA10 simulator: Add the PANDA_LIGHTS and the PIDP10 options for frontpanel +## code. + +import simgen.basic_simulator as SBS + +class KA10Simulator(SBS.SIMHBasicSimulator): + def __init__(self, sim_name, dir_macro, test_name, buildrom): + super().__init__(sim_name, dir_macro, test_name, buildrom) + + def write_simulator(self, stream, indent, test_label='ka10'): + ## Keep the CMake options separate, just in case they are needed for more + ## than just the KA10 (and add a class variable so they are only written + ## once.) + stream.write(''' +option(PANDA_LIGHTS + "Enable (=1)/disable (=0) KA-10/KI-11 simulator\'s Panda display. (def: disabled)" + FALSE) +option(PIDP10 + "Enable (=1)/disable (=0) PIDP10 display options (def: disabled)" + FALSE) + +### Ensure that the options are mutually exclusive: +if (PANDA_LIGHTS AND PIDP10) + message(FATAL_ERROR "PANDA_LIGHTS and PIDP10 options are mutually exclusive. Choose one.") +endif () + + +''') + ## Emit the simulator: + super().write_simulator(stream, indent, test_label) + ## Update the display sources for PANDA_LIGHTS or PIDP10: + stream.write('\n'.join([ + '', + 'if (PANDA_LIGHTS)', + ' target_sources({0} PUBLIC {1}/kx10_lights.c)'.format(self.sim_name, self.dir_macro), + ' target_compile_definitions({0} PUBLIC PANDA_LIGHTS)'.format(self.sim_name), + ' target_link_libraries({0} PUBLIC usb-1.0)'.format(self.sim_name), + 'endif ()', + 'if (PIDP10)', + ' target_sources({0} PUBLIC {1}/ka10_pipanel.c)'.format(self.sim_name, self.dir_macro), + ' target_compile_definitions({0} PUBLIC PIDP10=1)'.format(self.sim_name), + 'endif ()' + ])) + stream.write('\n') + diff --git a/cmake/simgen/sim_collection.py b/cmake/simgen/sim_collection.py index d4ca850c..dd866c70 100644 --- a/cmake/simgen/sim_collection.py +++ b/cmake/simgen/sim_collection.py @@ -2,6 +2,8 @@ import pprint import simgen.parse_makefile as SPM import simgen.basic_simulator as SBS +import simgen.ibm1130_simulator as IBM1130 +import simgen.pdp10_simulator as PDP10 import simgen.vax_simulators as VAXen import simgen.utils as SU @@ -16,8 +18,8 @@ _special_vars = frozenset(['DISPLAYL', _special_simulators = { "besm6": SBS.BESM6Simulator, "i650": SBS.IBM650Simulator, - "ibm1130": SBS.IBM1130Simulator, - "pdp10-ka": SBS.KA10Simulator, + "ibm1130": IBM1130.IBM1130Simulator, + "pdp10-ka": PDP10.KA10Simulator, "vax": VAXen.VAXSimulator, "vax730": VAXen.BasicVAXSimulator } diff --git a/cmake/simgen/simulators.py b/cmake/simgen/simulators.py deleted file mode 100644 index 71e8b406..00000000 --- a/cmake/simgen/simulators.py +++ /dev/null @@ -1,75 +0,0 @@ -"3b2" -"3b2-700" -"altair" -"altairz80" -"b5500" -"besm6" -"cdc1700" -"eclipse" -"gri" -"h316" -"hp2100" -"hp3000" -"i1401" -"i1620" -"i650" -"i701" -"i7010" -"i704" -"i7070" -"i7080" -"i7090" -"i7094" -"ibm1130" -"id16" -"id32" -"imlac" -"infoserver100" -"infoserver1000" -"infoserver150vxt" -"intel-mds" -"lgp" -"microvax1" -"microvax2" -"microvax2000" -"microvax3100" -"microvax3100e" -"microvax3100m80" -"microvax3900" -"nova" -"pdp1" -"pdp10" -"pdp10-ka" -"pdp10-ki" -"pdp10-kl" -"pdp10-ks" -"pdp11" -"pdp15" -"pdp4" -"pdp6" -"pdp7" -"pdp8" -"pdp9" -"rtvax1000" -"s3" -"scelbi" -"sds" -"sel32" -"sigma" -"ssem" -"swtp6800mp-a" -"swtp6800mp-a2" -"tt2500" -"tx-0" -"uc15" -"vax" -"vax730" -"vax750" -"vax780" -"vax8200" -"vax8600" -"vaxstation3100m30" -"vaxstation3100m38" -"vaxstation3100m76" -"vaxstation4000m60" -"vaxstation4000vlc" \ No newline at end of file diff --git a/cmake/simgen/vax_simulators.py b/cmake/simgen/vax_simulators.py index e2cba2d2..60e19eb3 100644 --- a/cmake/simgen/vax_simulators.py +++ b/cmake/simgen/vax_simulators.py @@ -1,3 +1,5 @@ +## VAX simulators require extra magic -- notably, 'microvax3900${EXE}' needs +## to be symlinked, hardlinked or copied (in that order) to 'vax${EXE}'. import simgen.basic_simulator as SBS diff --git a/scp.c b/scp.c index 8c7a3f31..ae53b5e1 100644 --- a/scp.c +++ b/scp.c @@ -2738,6 +2738,7 @@ char cbuf[4*CBUFSIZE], *cptr, *cptr2; char nbuf[PATH_MAX + 7]; char **targv = NULL; int32 i, sw; +int first_arg = -1; t_bool lookswitch; t_bool register_check = FALSE; t_stat stat = SCPE_OK; @@ -2783,6 +2784,7 @@ for (i = 1; i < argc; i++) { /* loop thru args */ if (*cbuf) /* concat args */ strlcat (cbuf, " ", sizeof (cbuf)); sprintf(&cbuf[strlen(cbuf)], "%s%s%s", strchr(argv[i], ' ') ? "\"" : "", argv[i], strchr(argv[i], ' ') ? "\"" : ""); + first_arg = i; lookswitch = FALSE; /* no more switches */ } } /* end for */ @@ -2894,7 +2896,7 @@ if (register_check) { goto cleanup_and_exit; } sim_printf ("*** Good Registers in %s simulator.\n", sim_name); - if (argc < 2) { /* No remaining command arguments? */ + if (first_arg < 0) { /* No remaining command arguments? */ sim_exit_status = EXIT_SUCCESS; /* then we're done */ goto cleanup_and_exit; } @@ -8053,7 +8055,8 @@ t_stat reset_all_p (uint32 start) t_stat r; int32 old_sw = sim_switches; -sim_switches = SWMASK ('P'); +/* Add power-up reset to the sim switches. */ +sim_switches = sim_switches | SWMASK ('P'); r = reset_all (start); sim_switches = old_sw; return r;