downtest and bonus test work in mmu updown

This commit is contained in:
Neil Webber 2023-09-16 22:19:36 -05:00
parent a909323cd8
commit a74312451a

View file

@ -669,7 +669,9 @@ class TestMethods(unittest.TestCase):
# to execute this in isolation just to generate the instructions # to execute this in isolation just to generate the instructions
# and use them in other simulators (e.g., SIMH) # and use them in other simulators (e.g., SIMH)
# #
# Returns a tuple (t, u, k) each being an InstructionBlock # Returns three tuples:
# (taddr, t), (uaddr, u), (k addr, k)
# where the t/u/k elements are the instruction blocks.
cn = self.usefulconstants() cn = self.usefulconstants()
@ -681,8 +683,8 @@ class TestMethods(unittest.TestCase):
# taddr and kaddr MUST be in this first 8K of memory (if only # taddr and kaddr MUST be in this first 8K of memory (if only
# because the mapping setup doesn't map anything else) # because the mapping setup doesn't map anything else)
# #
# USER I space is mapped to uaddr which can be any 8K boundary # USER I space is mapped to uaddr which can be any 64-byte
# 0o20000 and beyond. # (i.e., mappable to user 0) boundary 0o20000 and beyond.
# #
# All 64K of USER D space is mapped to 64K of physical memory # All 64K of USER D space is mapped to 64K of physical memory
# from uphysdata to uphysdata + 64K, but with a bizarre page # from uphysdata to uphysdata + 64K, but with a bizarre page
@ -713,6 +715,11 @@ class TestMethods(unittest.TestCase):
# using ED=1 ("dirbit" = 0o10) segments grow downwards, with the # using ED=1 ("dirbit" = 0o10) segments grow downwards, with the
# same 0, 16, 32 .. progression (of valid "blocks") but they # same 0, 16, 32 .. progression (of valid "blocks") but they
# are at the end of the segments. # are at the end of the segments.
#
# This test can be rightly criticized as unnecessarily complex;
# once the math has been shown correct for a few important length
# cases to consider, the possibility of further bugs is remote.
# Nevertheless, here it is.
# this code will go at taddr # this code will go at taddr
with ASM() as tr: with ASM() as tr:
@ -724,7 +731,7 @@ class TestMethods(unittest.TestCase):
# gets to use r2-r5: # gets to use r2-r5:
# r2: expected good flag (initialized elsewhere) # r2: expected good flag (initialized elsewhere)
# r3: determined good flag (by trap entry) # r3: determined good flag (by trap entry)
# r5: TESTTABLE pointer (initialized elsewhere) # r5: test table data pointer (initialized elsewhere)
tr.label('UTrap') tr.label('UTrap')
# first determine if trap0 (bad) or trap1 (good) # first determine if trap0 (bad) or trap1 (good)
@ -832,7 +839,9 @@ class TestMethods(unittest.TestCase):
# The kernel-mode code that drives the whole test # The kernel-mode code that drives the whole test
with ASM() as k: with ASM() as k:
k.mov(0o20000, 'sp') # start system stack at 8k # location 0o17776 is used to remember the table start r5...
k.mov(0o17776, 'sp') # start system stack at 8k - 2
# KERNEL I SPACE # KERNEL I SPACE
# PAR 0 to physical 0 # PAR 0 to physical 0
# PAR 7 to physical 760000 and 22bit not turned on # PAR 7 to physical 760000 and 22bit not turned on
@ -923,6 +932,8 @@ class TestMethods(unittest.TestCase):
# create the test table, just push it onto the stack (yeehah!) # create the test table, just push it onto the stack (yeehah!)
k.mov(0, '-(sp)') # this is a PAD (not really needed) k.mov(0, '-(sp)') # this is a PAD (not really needed)
k.mov(0o666, '-(sp)') # this is a sentinel k.mov(0o666, '-(sp)') # this is a sentinel
k.mov(0, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o176100, '-(sp)') k.mov(0o176100, '-(sp)')
k.mov(1, '-(sp)') k.mov(1, '-(sp)')
k.mov(0o160000, '-(sp)') k.mov(0o160000, '-(sp)')
@ -956,6 +967,7 @@ class TestMethods(unittest.TestCase):
# the test table for the trap handler is now here: # the test table for the trap handler is now here:
k.mov('sp', 'r5') k.mov('sp', 'r5')
k.mov('sp', '*$17776') # it is also stored here for re-use
# test starts in the region at the start of the table # test starts in the region at the start of the table
k.mov('(r5)', 'r2') k.mov('(r5)', 'r2')
@ -973,12 +985,53 @@ class TestMethods(unittest.TestCase):
k.clr('r0') # user test expects r0 to start zero k.clr('r0') # user test expects r0 to start zero
k.rtt() k.rtt()
# these instructions will be used to switch over # this is where the DOWN test starts.
# to the DOWN phase of the test. Similar to the UP but k.label('DOWNTEST')
# don't have to do the PARs (they stay the same) and the
# pln calculations are different.
k.label('DOWN') # re-establish initial kernel stack
k.mov(0o17776, 'sp')
# Redo the entire test table for the down address cases
# these were precomputed from the algorithm for setting PDRs
k.mov(0, '-(sp)')
k.mov(0o666, '-(sp)')
k.mov(0, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o161700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o160000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o143700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o140000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o125700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o120000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o107700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o100000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o71700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o60000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o53700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o40000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o35700, '-(sp)')
k.mov(0, '-(sp)')
k.mov(0o20000, '-(sp)')
k.mov(1, '-(sp)')
k.mov(0o17700, '-(sp)')
k.mov(1, '-(sp)')
k.mov('sp', 'r5') # r5 is where the table starts
k.mov('sp', '*$17776') # it is also stored here for re-use
# fiddle the PDRs (PARs stay the same) for the down configuration
k.mov(cn.UDSD0, 'r3') k.mov(cn.UDSD0, 'r3')
k.clr('r0') k.clr('r0')
k.label('PARloopDOWN') k.label('PARloopDOWN')
@ -997,11 +1050,12 @@ class TestMethods(unittest.TestCase):
k.cmp('r0', 16) k.cmp('r0', 16)
k.blt('PARloopDOWN') k.blt('PARloopDOWN')
# this halt will be right before the first run of user mode test k.clr('r2') # the down test starts in 'bad' zone
k.halt()
k.clr('r0') # initial loop condition # ok, now ready to start the user program
k.clr('(sp)') # just knows the user loop starts at zero k.mov(0o140340, '-(sp)') # push user-ish PSW to K stack
k.clr('-(sp)') # new user PC = 0
k.clr('r0') # user test expects r0 to start zero
k.rtt() k.rtt()
# Now for something extra frosty... relocate just segment 4 # Now for something extra frosty... relocate just segment 4
@ -1011,6 +1065,9 @@ class TestMethods(unittest.TestCase):
# relocation (note: I space because no sep I/D for kernel here) # relocation (note: I space because no sep I/D for kernel here)
k.label('BONUS') k.label('BONUS')
# recover the r5 stack table beginning
k.mov('*$17776', 'r5')
# copy UDSA4 into KISA1 - mapping old segment into kernel space # copy UDSA4 into KISA1 - mapping old segment into kernel space
k.mov(k.ptr(cn.UDSA0 + 4*2), k.ptr(cn.KISA0 + 2)) # i.e., A1 k.mov(k.ptr(cn.UDSA0 + 4*2), k.ptr(cn.KISA0 + 2)) # i.e., A1
@ -1032,8 +1089,8 @@ class TestMethods(unittest.TestCase):
# switch the user page to the new mapping # switch the user page to the new mapping
k.mov(0o6000, k.ptr(cn.UDSA0 + 4*2)) k.mov(0o6000, k.ptr(cn.UDSA0 + 4*2))
# and the standard initialization/resume dance # and the standard initialization dance
k.halt() k.clr('r2') # the down test starts in 'bad' zone
k.clr('r0') k.clr('r0')
k.clr('(sp)') # just knows the user loop starts at zero k.clr('(sp)') # just knows the user loop starts at zero
k.rtt() k.rtt()
@ -1089,52 +1146,30 @@ class TestMethods(unittest.TestCase):
uaddr = 0o20000 uaddr = 0o20000
for addr, b in self._make_updown(taddr, uaddr, kaddr): for addr, b in self._make_updown(taddr, uaddr, kaddr):
if addr == kaddr:
# need to know DOWNTEST and BONUS
downtest = kaddr + (2 * b.getlabel('DOWNTEST'))
bonus = kaddr + (2 * b.getlabel('BONUS'))
self.loadphysmem(p, b.instructions(), addr) self.loadphysmem(p, b.instructions(), addr)
# finally ready to run the whole shebang! with self.subTest(phase="UP"):
p.run(pc=kaddr) # finally ready to run the whole shebang!
p.run(pc=kaddr)
# a halt was encountered, verify r2 is the end sentinel # a halt was encountered, verify r2 is the end sentinel
self.assertEqual(p.r[2], 0o666) self.assertEqual(p.r[2], 0o666)
return
# this will be used for both up/down testing, based on goodf with self.subTest(phase="DOWN"):
def _test(goodf): # run the down test
previous_good = True p.r[2] = 0 # superfluous but makes sure
p.run(pc=downtest)
self.assertEqual(p.r[2], 0o666)
for segno in range(8): with self.subTest(phase="BONUS"):
for o in range(4096): # and the bonus test
p.run() # picks up at rtt pc p.r[2] = 0 # superfluous but makes sure
physval = (checksum - p.run(pc=bonus)
((segno * 8192) + (o * 2))) & 0o177777 self.assertEqual(p.r[2], 0o666)
if goodf(segno, o*2):
r5_expected = 0o42
r1_expected = physval
if not previous_good:
print(f"bad to good at r0={oct(p.r[0])}, "
f"addr = {oct(segno*8192 + (2*o))}")
previous_good = True
else:
r5_expected = 0o666
r1_expected = user_noval
if previous_good:
print(f"good to bad at r0={oct(p.r[0])}, "
f"addr = {oct(segno*8192 + (2*o))}")
previous_good = False
self.assertEqual(p.r[1], r1_expected)
self.assertEqual(p.r[5], r5_expected)
# run the UP test:
_test(lambda _segno, _o: _o <= (63 + ((_segno * 64) * 16)))
# run the code to convert over to DOWN MMU format, and then the test
p.run(pc=kernel_addr + (a.getlabel('DOWN') * 2))
_test(lambda _segno, _o: _o >= 8192 - (64 + ((_segno * 64) * 16)))
# last but not least, the BONUS test
p.run(pc=kernel_addr + (a.getlabel('BONUS') * 2))
_test(lambda _segno, _o: _o >= 8192 - (64 + ((_segno * 64) * 16)))
def test_ubmap(self): def test_ubmap(self):
p = self.make_pdp() p = self.make_pdp()