invis
This commit is contained in:
parent
fd03a30e4c
commit
d07363b983
1 changed files with 40 additions and 25 deletions
65
mmu.py
65
mmu.py
|
@ -258,9 +258,15 @@ class MemoryMgmt:
|
||||||
if self._22bit:
|
if self._22bit:
|
||||||
self.iopage_base |= (15 << 18) # ... and 4 more
|
self.iopage_base |= (15 << 18) # ... and 4 more
|
||||||
|
|
||||||
def v2p(self, vaddr, mode, space, reading):
|
def v2p(self, vaddr, mode, space, reading, *, invis=False):
|
||||||
"""Convert a 16-bit virtual address to physical.
|
"""Convert a 16-bit virtual address to physical.
|
||||||
NOTE: Raises traps, updates A/W bits, & sets straps as needed.
|
|
||||||
|
invis=True when being used for logging or other examinations that
|
||||||
|
should not alter any machine state, including MMU state.
|
||||||
|
|
||||||
|
NOTE: raises PDPTraps.MMU for untranslatable addresses
|
||||||
|
NOTE: If not invis, updates A/W bits & sets straps as needed.
|
||||||
|
* Raises traps, updates A/W bits, & sets straps as needed.
|
||||||
NOTE: 'reading' MUST be True or False, not anything else.
|
NOTE: 'reading' MUST be True or False, not anything else.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -332,15 +338,15 @@ class MemoryMgmt:
|
||||||
# handler modifies the APR to disable the management trap then
|
# handler modifies the APR to disable the management trap then
|
||||||
# of course future lookups will be eligible for the cache then.
|
# of course future lookups will be eligible for the cache then.
|
||||||
|
|
||||||
straps = self._v2p_accesschecks(pdr, vaddr, xkey)
|
straps = self._v2p_accesschecks(pdr, vaddr, xkey, invis)
|
||||||
|
|
||||||
# the actual translation...
|
# the actual translation...
|
||||||
bn = (vaddr >> 6) & 0o177
|
bn = (vaddr >> 6) & 0o177
|
||||||
plf = (pdr >> 8) & 0o177
|
plf = (pdr >> 8) & 0o177
|
||||||
if (pdr & 0o10) and bn < plf:
|
if (pdr & 0o10) and bn < plf:
|
||||||
self._raisetrap(self.MMR0_BITS.ABORT_PLENGTH, vaddr, xkey)
|
self._raisetrap(self.MMR0_BITS.ABORT_PLENGTH, vaddr, xkey, invis)
|
||||||
elif (pdr & 0o10) == 0 and bn > plf:
|
elif (pdr & 0o10) == 0 and bn > plf:
|
||||||
self._raisetrap(self.MMR0_BITS.ABORT_PLENGTH, vaddr, xkey)
|
self._raisetrap(self.MMR0_BITS.ABORT_PLENGTH, vaddr, xkey, invis)
|
||||||
|
|
||||||
# "Attention" (not "Access") and "Written" bits updates.
|
# "Attention" (not "Access") and "Written" bits updates.
|
||||||
# The W bit is indeed a "memory was written" bit.
|
# The W bit is indeed a "memory was written" bit.
|
||||||
|
@ -352,21 +358,20 @@ class MemoryMgmt:
|
||||||
# there are no further A/W bit updates to worry about (so they
|
# there are no further A/W bit updates to worry about (so they
|
||||||
# can be cached at that point).
|
# can be cached at that point).
|
||||||
|
|
||||||
W_update = 0o000 if reading else 0o100
|
if not invis:
|
||||||
A_update = 0o200 if straps else 0o000
|
self.cpu.straps |= straps
|
||||||
|
W_update = 0o000 if reading else 0o100
|
||||||
|
A_update = 0o200 if straps else 0o000
|
||||||
|
AW_update = (W_update | A_update)
|
||||||
|
|
||||||
AW_update = (W_update | A_update)
|
if (pdr & AW_update) != AW_update:
|
||||||
|
self._putapr(xkey, (par, pdr | AW_update))
|
||||||
if (pdr & AW_update) != AW_update:
|
|
||||||
self._putapr(xkey, (par, pdr | AW_update))
|
|
||||||
|
|
||||||
dib = vaddr & 0o77
|
dib = vaddr & 0o77
|
||||||
pa = ((par + bn) << 6) | dib
|
pa = ((par + bn) << 6) | dib
|
||||||
|
|
||||||
self.cpu.straps |= straps
|
|
||||||
|
|
||||||
# only non-trapping can be cached
|
# only non-trapping can be cached
|
||||||
if straps == 0:
|
if straps == 0 and not invis:
|
||||||
self._encache(tuplexkey, pdr, pa - vaddr)
|
self._encache(tuplexkey, pdr, pa - vaddr)
|
||||||
return pa
|
return pa
|
||||||
|
|
||||||
|
@ -412,7 +417,7 @@ class MemoryMgmt:
|
||||||
foldednth = (xkey.mode * 2) + self._foldspaces(xkey.mode, xkey.space)
|
foldednth = (xkey.mode * 2) + self._foldspaces(xkey.mode, xkey.space)
|
||||||
self.APR[foldednth][xkey.segno] = list(apr)
|
self.APR[foldednth][xkey.segno] = list(apr)
|
||||||
|
|
||||||
def _v2p_accesschecks(self, pdr, vaddr, xkey):
|
def _v2p_accesschecks(self, pdr, vaddr, xkey, invis):
|
||||||
"""Raise traps or set post-instruction traps as appropriate.
|
"""Raise traps or set post-instruction traps as appropriate.
|
||||||
|
|
||||||
Returns straps flags (if any required).
|
Returns straps flags (if any required).
|
||||||
|
@ -454,14 +459,15 @@ class MemoryMgmt:
|
||||||
f"{list(map(oct, self.cpu.r))}"
|
f"{list(map(oct, self.cpu.r))}"
|
||||||
f", {oct(self.cpu.psw)}"
|
f", {oct(self.cpu.psw)}"
|
||||||
f", PDR={oct(pdr)} {reading=}")
|
f", PDR={oct(pdr)} {reading=}")
|
||||||
self._raisetrap(self.MMR0_BITS.ABORT_NR, vaddr, xkey)
|
self._raisetrap(self.MMR0_BITS.ABORT_NR, vaddr, xkey, invis)
|
||||||
|
|
||||||
# control mode 1 is an abort if writing, mgmt trap if read
|
# control mode 1 is an abort if writing, mgmt trap if read
|
||||||
case 1 if reading:
|
case 1 if reading:
|
||||||
straps = self.cpu.STRAPBITS.MEMMGT
|
straps = self.cpu.STRAPBITS.MEMMGT
|
||||||
|
|
||||||
case 1 | 2 if not reading:
|
case 1 | 2 if not reading:
|
||||||
self._raisetrap(self.MMR0_BITS.ABORT_RDONLY, vaddr, xkey)
|
self._raisetrap(
|
||||||
|
self.MMR0_BITS.ABORT_RDONLY, vaddr, xkey, invis)
|
||||||
|
|
||||||
# control mode 4 is mgmt trap on any access (read or write)
|
# control mode 4 is mgmt trap on any access (read or write)
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -473,14 +479,15 @@ class MemoryMgmt:
|
||||||
|
|
||||||
return straps
|
return straps
|
||||||
|
|
||||||
def wordRW(self, vaddr, value=None, /, *, mode=None, space=ISPACE):
|
def wordRW(self, vaddr, value=None, /, *,
|
||||||
|
mode=None, space=ISPACE, _invis=False):
|
||||||
"""Read/write a word at virtual address vaddr.
|
"""Read/write a word at virtual address vaddr.
|
||||||
|
|
||||||
If value is None, perform a read and return a 16-bit value
|
If value is None, perform a read and return a 16-bit value
|
||||||
If value is not None, perform a write; return None.
|
If value is not None, perform a write; return None.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pa = self.v2p(vaddr, mode, space, value is None)
|
pa = self.v2p(vaddr, mode, space, value is None, invis=_invis)
|
||||||
if pa >= self.iopage_base:
|
if pa >= self.iopage_base:
|
||||||
return self.ub.mmio.wordRW(pa & self.cpu.IOPAGE_MASK, value)
|
return self.ub.mmio.wordRW(pa & self.cpu.IOPAGE_MASK, value)
|
||||||
else:
|
else:
|
||||||
|
@ -544,17 +551,25 @@ class MemoryMgmt:
|
||||||
self.cpu.physRW(pa & ~1, wv)
|
self.cpu.physRW(pa & ~1, wv)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# because faults will change MMR registers and CPUERR... this exists
|
||||||
|
# so debugging/logging tools (e.g., machinestate()) can access
|
||||||
|
# memory without disturbing MMU/cpu state if a fault is caused.
|
||||||
|
def _invisread(self, a):
|
||||||
|
"""For debugging; read invisibly w/out modifying any MMU/CPU state."""
|
||||||
|
return self.wordRW(a, _invis=True)
|
||||||
|
|
||||||
def wordRW_KD(self, a, v=None, /):
|
def wordRW_KD(self, a, v=None, /):
|
||||||
"""Convenienence; version of wordRW for kernel/dspace."""
|
"""Convenienence; version of wordRW for kernel/dspace."""
|
||||||
return self.wordRW(a, v, mode=self.cpu.KERNEL, space=self.DSPACE)
|
return self.wordRW(a, v, mode=self.cpu.KERNEL, space=self.DSPACE)
|
||||||
|
|
||||||
def _raisetrap(self, trapflag, vaddr, xkey):
|
def _raisetrap(self, trapflag, vaddr, xkey, invis):
|
||||||
"""Raise an MMU trap. Commits regmods and updates reason in MMR0."""
|
"""Raise an MMU trap. Commits regmods and updates reason in MMR0."""
|
||||||
self._MMR1commit()
|
if not invis:
|
||||||
self.MMR0 |= (trapflag |
|
self._MMR1commit()
|
||||||
xkey.segno << 1 | # bits <3:1>
|
self.MMR0 |= (trapflag |
|
||||||
xkey.space << 4 | # bit 4
|
xkey.segno << 1 | # bits <3:1>
|
||||||
xkey.mode << 5) # bits <6:5>
|
xkey.space << 4 | # bit 4
|
||||||
|
xkey.mode << 5) # bits <6:5>
|
||||||
|
|
||||||
# XXX gotta figure out how to set this for Odd Addresses and
|
# XXX gotta figure out how to set this for Odd Addresses and
|
||||||
# T bit conditions, but otherwise Bit 7 is not set. From handbook:
|
# T bit conditions, but otherwise Bit 7 is not set. From handbook:
|
||||||
|
|
Loading…
Add table
Reference in a new issue