CMake: Make generate.py reusable
Make generate.py resuable outside of open-simh, as suggested and motivated by Richard Cornwell's simulator repository. - Make the "experimental" rule optional. Do not generate a Python "KeyError" if the rule is missing. - Add documentation on how to use the CMake infrastructure outside of open-simh: Customize the packaging.py script, season to taste. - Update the KA10 simulator customization, moving it to its own Python script, simgen/pdp10_simulator.py. Preparatory move that anticipates additional frontpanel and display options. - generate.py option "--skip-orphans": Skip the orphaned simulator check (i.e., don't cross-reference the simulators in packaging.py with what was scraped from the makefile.) - Add "TEST_ARGS" argument to CMake's add_simulator function so that the IBM 1130 simulator can pass to "-g" on the command line to disable the GUI when running RegisterSanityCheck, i.e.: ibm1130 RegisterSanityCheck -g This fixes an edge case Heisenbug encountered during Github CI/CD tests where ibm1130 appears to hang indefinitely on the Windows runners. The cause is the GUI's Pump() thread function being prematurely terminated before all GUI resources are acquired. The net result is an infinite loop in the MS C runtime trying to exit the process with unstable internal state. (Separate patch: synchronization across main and Pump() threads to ensure resource acquisition completes.) This issue never shows up on non-Windows platforms or the SIMH makefile. - cmake/generator.py, cmake/simgen: Add a "test_args" keyword argument to the BasicSimulator constructor that holds the tests argument parameter emitted as the "TEST_ARGS" argument to a simulator's add_simulator(). Ensure that the IBM 1130 emits 'TEST_ARG "-g"' in its add_simulator(). - scp.c: reset_all_p() adds 'P' to the existing switches, versus saving sim_switches and ONLY setting the 'P' power-up reset switch. Net effect is that the IBM 1130 simulator actually sees the 'G' flag that inhibits the GUI during the console device reset.
This commit is contained in:
parent
24f145ad16
commit
191b2131e9
15 changed files with 342 additions and 169 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,6 +42,7 @@ def process_makefile(makefile_dir, debug=0):
|
|||
walk_target_deps(all_targ, defs, rules, actions, simulators, debug=debug)
|
||||
|
||||
experimental_rule = rules.get('experimental')
|
||||
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)
|
||||
|
@ -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()
|
||||
|
||||
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()
|
||||
|
|
|
@ -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__
|
||||
|
|
30
cmake/simgen/ibm1130_simulator.py
Normal file
30
cmake/simgen/ibm1130_simulator.py
Normal file
|
@ -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)',
|
||||
''
|
||||
]))
|
||||
|
||||
|
|
@ -30,8 +30,10 @@ 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)
|
||||
|
||||
if len(sims) > 0:
|
||||
sims.sort()
|
||||
pkg_description += " Simulators: " + ', '.join(sims)
|
||||
indent0 = ' ' * indent
|
||||
|
|
|
@ -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 = []
|
||||
|
|
45
cmake/simgen/pdp10_simulator.py
Normal file
45
cmake/simgen/pdp10_simulator.py
Normal file
|
@ -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')
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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
|
||||
|
||||
|
|
7
scp.c
7
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue