downtest and bonus test work in mmu updown
This commit is contained in:
parent
a909323cd8
commit
a74312451a
1 changed files with 92 additions and 57 deletions
149
pdptests.py
149
pdptests.py
|
@ -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()
|
||||||
|
|
Loading…
Add table
Reference in a new issue