From d0b0c2f25ae653db9c8c7d0ed16e0073a85761cc Mon Sep 17 00:00:00 2001
From: Neil Webber <neil@webber.com>
Date: Fri, 15 Sep 2023 06:15:10 -0400
Subject: [PATCH] Made _CYCLE an Enum

---
 mmu.py | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/mmu.py b/mmu.py
index 6449808..0cfeaeb 100644
--- a/mmu.py
+++ b/mmu.py
@@ -24,13 +24,20 @@ from functools import partial
 from pdptraps import PDPTraps
 from types import SimpleNamespace
 from collections import namedtuple
+from enum import Enum
+
+
+# used internally to represent reads vs writes
+class _CYCLE(Enum):
+    READ = 'r'
+    WRITE = 'w'
 
 
 class MemoryMgmt:
     ISPACE = 0
     DSPACE = 1
 
-    # I/O addreses for various registers relative to I/O page base
+    # I/O addresses for various registers relative to I/O page base
     # From the pdp11/70 (and others) 1981 processor handbook, Appendix A
     #
     # Each block is:
@@ -61,9 +68,6 @@ class MemoryMgmt:
     # memory control (parity, etc) is not implemented but needs to respond
     MCR_OFFS = 0o17746
 
-    # encodes read vs write cycles
-    CYCLE = SimpleNamespace(READ='r', WRITE='w')
-
     TransKey = namedtuple('TransKey', ('segno', 'mode', 'space', 'cycle'))
 
     def __init__(self, cpu, /, *, nocache=False):
@@ -146,9 +150,9 @@ class MemoryMgmt:
             return aprfile[aprnum][parpdr]
         else:
             # dump any matching cache entries in both reading/writing form.
-            for w in (self.CYCLE.READ, self.CYCLE.WRITE):
-                if (aprnum, mode, space, w) in self.segcache:
-                    del self.segcache[(aprnum, mode, space, w)]
+            for rw in (_CYCLE.READ, _CYCLE.WRITE):
+                if (aprnum, mode, space, rw) in self.segcache:
+                    del self.segcache[(aprnum, mode, space, rw)]
 
             aprfile[aprnum][parpdr] = value
 
@@ -330,7 +334,7 @@ class MemoryMgmt:
         # already happened (here). So the "found it in cache" logic up top
         # of this function needn't worry about AW bit updates.
 
-        AW_update = 0o300 if cycle == self.CYCLE.WRITE else 0o200
+        AW_update = 0o300 if cycle == _CYCLE.WRITE else 0o200
         #       XXX ^^^^^ not sure if a write should be 0o300 or naked 0o100
 
         if (pdr & AW_update) != AW_update:
@@ -417,10 +421,10 @@ class MemoryMgmt:
                 self._raisetrap(self.MMR0_BITS.ABORT_NR, vaddr, xkey)
 
             # control mode 1 is an abort if writing, mgmt trap if read
-            case 1 if cycle == self.CYCLE.READ:
+            case 1 if cycle == _CYCLE.READ:
                 straps = self.cpu.STRAPBITS.MEMMGT
 
-            case 1 | 2 if cycle == self.CYCLE.WRITE:
+            case 1 | 2 if cycle == _CYCLE.WRITE:
                 self._raisetrap(self.MMR0_BITS.ABORT_RDONLY, vaddr, xkey)
 
             # control mode 4 is mgmt trap on any access (read or write)
@@ -428,7 +432,7 @@ class MemoryMgmt:
                 straps = self.cpu.STRAPBITS.MEMMGT
 
             # control mode 5 is mgmt trap if WRITING
-            case 5 if cycle == self.CYCLE.WRITE:
+            case 5 if cycle == _CYCLE.WRITE:
                 straps = self.cpu.STRAPBITS.MEMMGT
 
         return straps
@@ -440,7 +444,7 @@ class MemoryMgmt:
         If value is not None, perform a write; return None.
         """
 
-        cycle = self.CYCLE.READ if value is None else self.CYCLE.WRITE
+        cycle = _CYCLE.READ if value is None else _CYCLE.WRITE
         pa = self.v2p(vaddr, mode, space, cycle)
         if pa >= self.iopage_base:
             return self.ub.mmio.wordRW(pa & self.cpu.IOPAGE_MASK, value)
@@ -454,7 +458,7 @@ class MemoryMgmt:
         If value is not None, perform a write; return None.
         """
 
-        cycle = self.CYCLE.READ if value is None else self.CYCLE.WRITE
+        cycle = _CYCLE.READ if value is None else _CYCLE.WRITE
         pa = self.v2p(vaddr, mode, space, cycle)
 
         # Physical memory is represented as an array of 16-bit word