associate_device, devices, and fix steps
This commit is contained in:
parent
d5af85f09d
commit
140ce85120
1 changed files with 49 additions and 18 deletions
67
machine.py
67
machine.py
|
@ -159,7 +159,6 @@ class PDP11:
|
|||
def __init__(self, *,
|
||||
physmem=None, # default will be 512KB
|
||||
unibus=None, # subclasses may want to supply variant
|
||||
console=True, # automated tests need to turn this off
|
||||
logger="pdp11", loglevel='INFO',
|
||||
instlog=False, pswlog=False):
|
||||
|
||||
|
@ -244,20 +243,8 @@ class PDP11:
|
|||
# start off in halted state until .run() happens
|
||||
self.halted = True
|
||||
|
||||
# The console, the disk drive, and the clock are never really
|
||||
# accessed directly (everything is triggered through mmio I/O)
|
||||
# but of course must be instantiated
|
||||
if console: # it's helpful to disable for tests
|
||||
self._KL = KL11(self.ub)
|
||||
try:
|
||||
rp = RPRM(self.ub)
|
||||
except FileNotFoundError:
|
||||
self.logger.info("NO DISK DRIVE FILE FOUND; DISK DISABLED")
|
||||
else:
|
||||
self._RP = rp
|
||||
|
||||
# line clock
|
||||
self._KW = KW11(self.ub)
|
||||
# device instances; see add_device
|
||||
self.devices = {}
|
||||
|
||||
def physRW(self, physaddr, value=None):
|
||||
"""like MMU.wordRW but takes physical addresses."""
|
||||
|
@ -295,6 +282,49 @@ class PDP11:
|
|||
raise PDPTraps.AddressError(
|
||||
cpuerr=self.CPUERR_BITS.NXM) from None
|
||||
|
||||
# "associate" an emulated device
|
||||
#
|
||||
# Typically a device is instantiated by passing the unibus
|
||||
# attribute ('ub') of a PDP11 instance to its __init__ function:
|
||||
#
|
||||
# # p is a PDP11 instance
|
||||
# # XYZ11 is a device class
|
||||
#
|
||||
# device_instance = XYZ11(p.ub)
|
||||
#
|
||||
# The device __init__ will typically use ub.mmio.register to connect up
|
||||
# to its UNIBUS addresses. That's all that needs to happen.
|
||||
#
|
||||
# Nevertheless, on general principles, it seems like the pdp instance
|
||||
# should "know" about its devices, so ... this method.
|
||||
#
|
||||
# The typical code sequence would be:
|
||||
# p = PDP1170()
|
||||
# p.associate_device(XY11(p.ub), 'XY')
|
||||
# p.associate_device(AB11(p.ub), 'AB')
|
||||
# etc., combining instantiation ("XY11(p.ub)") and name association.
|
||||
#
|
||||
# HOWEVER, note that this works just as well:
|
||||
# p = PDP1170()
|
||||
# _ = XY11(p.ub)
|
||||
# _ = AB11(p.ub)
|
||||
# the devices just won't be discoverable via the devices attribute.
|
||||
# Device discovery via the devices attribute is not "architectural",
|
||||
# but may be useful for some test programs or other introspection.
|
||||
#
|
||||
def associate_device(self, dev, device_name=None, /):
|
||||
"""Associate the device instance 'dev' with 'device_name'
|
||||
|
||||
If device_name is None then __class__.__name__ is used.
|
||||
"""
|
||||
if device_name is None:
|
||||
device_name = dev.__class__.__name__
|
||||
|
||||
try:
|
||||
self.devices[device_name].append(dev)
|
||||
except KeyError:
|
||||
self.devices[device_name] = [dev]
|
||||
|
||||
# this the heart of all things related to 6-bit instruction operands.
|
||||
# If value is not given this will be a read
|
||||
# If value is given and not None, this will be a write
|
||||
|
@ -553,7 +583,7 @@ class PDP11:
|
|||
if steps is None:
|
||||
stepsgen = itertools.count()
|
||||
else:
|
||||
stepsgen = range(steps)
|
||||
stepsgen = range(steps-1)
|
||||
|
||||
try:
|
||||
stoppc, stopmode = stopat
|
||||
|
@ -562,6 +592,7 @@ class PDP11:
|
|||
stopmode = None
|
||||
|
||||
def _evalstop():
|
||||
icount = 0 # needed if steps == 1
|
||||
for icount in stepsgen:
|
||||
|
||||
# this is sneaky ... it's can be handy in debugging to
|
||||
|
@ -709,12 +740,12 @@ class PDP11:
|
|||
# Pulled out so can be overridden for specific debugging sceanrios.
|
||||
def instlogging(self, inst, pc):
|
||||
try:
|
||||
logit = self.instlog(self, inst, thisPC)
|
||||
logit = self.instlog(self, inst, pc)
|
||||
except TypeError:
|
||||
logit = True
|
||||
if logit:
|
||||
m = "KS!U"[self.psw_curmode]
|
||||
self.logger.debug(f"{oct(thisPC)}/{m} :: {oct(inst)}")
|
||||
self.logger.debug(f"{oct(pc)}/{m} :: {oct(inst)}")
|
||||
|
||||
@property
|
||||
def swleds(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue