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:
B. Scott Michel 2024-03-15 20:44:34 -07:00 committed by Paul Koning
parent 24f145ad16
commit 191b2131e9
15 changed files with 342 additions and 169 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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()

View file

@ -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__

View 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)',
''
]))

View file

@ -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

View file

@ -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 = []

View 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')

View file

@ -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
}

View file

@ -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"

View file

@ -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
View file

@ -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;