def run_io_interrupt(_, target): test_harness.build_program(['io_interrupt.S']) result = test_harness.run_program(target) lines = result.split('\n') output = None for line in lines: start = line.find('!') if start != -1: output = line[start + 1:] if output is None: raise test_harness.TestException( 'Could not find output string:\n' + result) # Make sure enough interrupts were triggered if output.count('*') < 2: raise test_harness.TestException( 'Not enough interrupts triggered:\n' + result) # Make sure we see at least some of the base string printed after an # interrupt if output.find('*') >= len(output) - 1: raise test_harness.TestException( 'No instances of interrupt return:\n' + result) # Remove all asterisks (interrupts) and make sure string is intact stripped = output.replace('*', '') if stripped != '0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`' \ 'abcdefghijklmnopqrstuvwxyz' * 10: raise test_harness.TestException( 'Base string does not match:\n' + stripped)
def shared_memory(_, target): """See coprocessor.c for an explanation of this test""" test_harness.build_program(['coprocessor.c']) # Start the emulator memory_file = tempfile.NamedTemporaryFile() args = [test_harness.BIN_DIR + 'emulator', '-s', memory_file.name, test_harness.HEX_FILE] process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) try: # Hack: Need to wait for the emulator to create the shared memory # file and initialize it. There's currently no way for the emulator # to signal that this has completed, so just sleep a bit and hope # it's done. time.sleep(1.0) memory = mmap.mmap(memory_file.fileno(), 0) testvalues = [random.randint(0, 0xffffffff) for __ in range(10)] for value in testvalues: computed = sharedmem_transact(memory, value) if computed != (value ^ 0xffffffff): raise test_harness.TestException('Incorrect value from coprocessor expected ' + hex(value ^ 0xffffffff) + ' got ' + hex(computed)) finally: process.kill()
def send_host_interrupt(_, target): try: os.remove(SEND_PIPE_NAME) except OSError: pass # Ignore if pipe doesn't exist test_harness.build_program(['send_host_interrupt.S']) os.mknod(SEND_PIPE_NAME, stat.S_IFIFO | 0o666) args = [test_harness.BIN_DIR + 'emulator', '-o', SEND_PIPE_NAME, test_harness.HEX_FILE] emulator_process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) try: interrupt_pipe = os.open(SEND_PIPE_NAME, os.O_RDONLY | os.O_NONBLOCK) test_harness.TimedProcessRunner().communicate(emulator_process, 60) # Interrupts should be in pipe now interrupts = os.read(interrupt_pipe, 5) if interrupts != b'\x05\x06\x07\x08\x09': raise test_harness.TestException( 'Did not receive proper host interrupts') finally: os.close(interrupt_pipe) os.unlink(SEND_PIPE_NAME)
def random_access_mmu_stress(_, target): test_harness.build_program(['random_access.S']) test_harness.run_program( target=target, dump_file='obj/vmem.bin', dump_base=DUMP_BASE, dump_length=MEMORY_SIZE * NUM_THREADS, timeout=240, flush_l2=True) # Check that threads have written proper values with open('obj/vmem.bin', 'rb') as memfile: for page_num in range(int(MEMORY_SIZE / PAGE_SIZE)): for thread_id in range(NUM_THREADS): for page_offset in range(0, PAGE_SIZE, 4): val = memfile.read(4) if len(val) < 4: raise test_harness.TestException( 'output file is truncated') num_val, = struct.unpack('<L', val) va = page_num * PAGE_SIZE + \ page_offset + int(DUMP_BASE / 4) expected = (thread_id << 24) | va if num_val != expected: raise test_harness.TestException( 'FAIL: mismatch @{:x} : got {:x} expected {:x}'.format((page_num * 4 + thread_id) * PAGE_SIZE, num_val, expected))
def sdmmc_write(_, target): with open(SOURCE_BLOCK_DEV, 'wb') as fsimage: fsimage.write(b'\xcc' * 1536) test_harness.build_program(['sdmmc_write.c']) result = test_harness.run_program( target=target, block_device=SOURCE_BLOCK_DEV) if 'FAIL' in result: raise test_harness.TestException('Test failed ' + result) with open(SOURCE_BLOCK_DEV, 'rb') as fsimage: end_contents = fsimage.read() # Check contents. First block is not modified for index in range(512): if end_contents[index] != 0xcc: raise test_harness.TestException('mismatch at {} expected 0xcc got 0x{:02x}' .format(index, end_contents[index])) # Second block has a pattern in it for index in range(512): expected = (index ^ (index >> 3)) & 0xff if end_contents[index + 512] != expected: raise test_harness.TestException('mismatch at {} expected 0x{:02x} got 0x{:02x}' .format(index + 512, expected, end_contents[index + 512])) # Third block is not modified for index in range(512): if end_contents[index + 1024] != 0xcc: raise test_harness.TestException('mismatch at {} expected 0xcc got 0x{:02x}' .format(index + 1024, end_contents[index + 1024]))
def run_compiler_test(source_file, target): if target == 'host': subprocess.check_call(['cc', source_file, '-o', 'obj/a.out'], stderr=subprocess.STDOUT) result = subprocess.check_output('obj/a.out') test_harness.check_result(source_file, result.decode()) else: test_harness.build_program([source_file]) result = test_harness.run_program(target) test_harness.check_result(source_file, result)
def kernel_globalinit(name): underscore = name.rfind('_') if underscore == -1: raise test_harness.TestException( 'Internal error: unknown environment') environment = name[underscore + 1:] test_harness.build_program(['constructor.cpp'], image_type='user') result = test_harness.run_kernel(environment=environment, timeout=120) test_harness.check_result('constructor.cpp', result)
def kernel_ucf(name): underscore = name.rfind('_') if underscore == -1: raise test_harness.TestException( 'Internal error: unknown environment') environment = name[underscore + 1:] test_harness.build_program(['user_copy_fault.c'], image_type='user') result = test_harness.run_kernel(environment=environment, timeout=120) test_harness.check_result('user_copy_fault.c', result)
def sdmmc_read(name, target): # Create random file with open(SOURCE_BLOCK_DEV, 'wb') as randfile: randfile.write(os.urandom(FILE_SIZE)) test_harness.build_program(['sdmmc_read.c']) test_harness.run_program( target=target, block_device=SOURCE_BLOCK_DEV, dump_file=MEMDUMP, dump_base=0x200000, dump_length=FILE_SIZE, flush_l2=True) test_harness.assert_files_equal(SOURCE_BLOCK_DEV, MEMDUMP, 'file mismatch')
def sdmmc_read(name): # Create random file with open(SOURCE_BLOCK_DEV, 'wb') as randfile: randfile.write(os.urandom(FILE_SIZE)) test_harness.build_program(['sdmmc_read.c']) test_harness.run_program( environment='emulator' if name.endswith('_emulator') else 'verilator', block_device=SOURCE_BLOCK_DEV, dump_file=MEMDUMP, dump_base=0x200000, dump_length=FILE_SIZE, flush_l2=True) test_harness.assert_files_equal(SOURCE_BLOCK_DEV, MEMDUMP, 'file mismatch')
def filesystem(_): ''' Filesystem tests. This creates a filesystem image with the test file fstest.txt in it, the compiles the program fs.c to perform operations on it. The program will print 'PASS' if it is successful. ''' test_harness.build_program(['fs.c']) subprocess.check_output( [test_harness.PROJECT_TOP + '/bin/mkfs', 'obj/fsimage.bin', 'fstest.txt'], stderr=subprocess.STDOUT) result = test_harness.run_program(environment='emulator', block_device='obj/fsimage.bin') if 'PASS' not in result: raise test_harness.TestException( 'test program did not indicate pass\n' + result)
def lldb(_): """This mainly validates that LLDB is reading symbols correctly.""" hexfile = test_harness.build_program( ['test_program.c'], opt_level='-O0', cflags=['-g']) with EmulatorProcess(hexfile) as conn: conn.send_command('file "obj/test.elf"') conn.send_command('gdb-remote 8000\n') response = conn.send_command( 'breakpoint set --file test_program.c --line 27') if 'Breakpoint 1: where = test.elf`func2 + 96 at test_program.c:27' not in response: raise test_harness.TestException( 'breakpoint: did not find expected value ' + response) conn.send_command('c') conn.wait_stop() expected_stack = [ ('func2', 'test_program.c', 27), ('func1', 'test_program.c', 35), ('main', 'test_program.c', 41), ('do_main', '', 0) ] response = conn.send_command('bt') crawl = parse_stack_crawl(response) if crawl != expected_stack: raise test_harness.TestException( 'stack crawl mismatch ' + str(crawl)) response = conn.send_command('print value') if '= 67' not in response: raise test_harness.TestException( 'print value: Did not find expected value ' + response) response = conn.send_command('print result') if '= 128' not in response: raise test_harness.TestException( 'print result: Did not find expected value ' + response) # Up to previous frame conn.send_command('frame select --relative=1') response = conn.send_command('print a') if '= 12' not in response: raise test_harness.TestException( 'print a: Did not find expected value ' + response) response = conn.send_command('print b') if '= 67' not in response: raise test_harness.TestException( 'print b: Did not find expected value ' + response) conn.send_command('step') conn.wait_stop() response = conn.send_command('print result') if '= 64' not in response: raise test_harness.TestException( 'print b: Did not find expected value ' + response)
def gdb_register_info(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Scalar registers for idx in range(28): regid = str(idx + 1) conn.expect('qRegisterInfo' + hex(idx + 1)[2:], 'name:s' + regid + ';bitsize:32;encoding:uint;format:hex;' 'set:General Purpose Scalar Registers;gcc:' + regid + ';dwarf:' + regid + ';') # These registers (sp, fp, ra) are special and have additional # information. names = ['fp', 'sp', 'ra'] for idx, name in zip(range(28, 32), names): regid = str(idx + 1) conn.expect('qRegisterInfo' + hex(idx + 1)[2:], 'name:s' + regid + ';bitsize:32;encoding:uint;format:hex;' 'set:General Purpose Scalar Registers;gcc:' + regid + ';dwarf:' + regid + ';generic:' + name + ';') # Vector registers for idx in range(32, 63): regid = str(idx + 1) conn.expect('qRegisterInfo' + hex(idx + 1)[2:], 'name:v' + str(idx - 31) + ';bitsize:512;encoding:uint;format:vector-uint32;' 'set:General Purpose Vector Registers;gcc:' + regid + ';dwarf:' + regid + ';') conn.expect('qRegisterInfo65', '')
def gdb_breakpoint(_, target): """ Validate stopping at a breakpoint and continuing after stopping. This sets two breakpoints """ hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Set breakpoint conn.expect('Z0,0000000c', 'OK') # Set second breakpoint at next instruction conn.expect('Z0,00000010', 'OK') # Continue conn.expect('C', 'S05') # Read last signal conn.expect('?', 'S05') # Read PC register. Should be 0x000000c, but endian swapped conn.expect('g40', '0c000000') # Read s0, which should be 3 conn.expect('g00', '03000000') # Continue again. conn.expect('C', 'S05') # Ensure the instruction it stopped at is # executed and it breaks on the next instruction conn.expect('g40', '10000000') # Read s0, which should be 4 conn.expect('g00', '04000000')
def run_cosimulation_test(source_file): hexfile = test_harness.build_program([source_file]) p1 = subprocess.Popen( verilator_args + ['+bin=' + hexfile], stdout=subprocess.PIPE) p2 = subprocess.Popen( emulator_args + [hexfile], stdin=p1.stdout, stdout=subprocess.PIPE) output = '' while True: got = p2.stdout.read(0x1000) if not got: break if verbose: print(str(got)) else: output += str(got) p2.wait() time.sleep(1) # Give verilator a chance to clean up p1.kill() # Make sure verilator has exited if p2.returncode: raise test_harness.TestException( 'FAIL: cosimulation mismatch\n' + output) test_harness.assert_files_equal(VERILATOR_MEM_DUMP, EMULATOR_MEM_DUMP, 'final memory contents to not match')
def gdb_read_write_register(_, target): hexfile = test_harness.build_program(['register_values.S']) with EmulatorProcess(hexfile), DebugConnection() as conn: # Run code to load registers conn.expect('C', 'S05') # Check values set by program (remote GDB returns in swapped byte # order...) conn.expect('g1', '7d7f3e85') conn.expect('g20', 'f13403ef9d08309993f7819954ae4b3f7aeaa28f538fecbd95' '36f59c6d7251269525ee70d26e8d34f48912639c86ae5dba426c83aa8455e1e2dbba4b41a4f321') tests = [ (0, 'd3839b18'), (1, '7b53cc78'), (30, '0904c47d'), (32, 'aef331bc7dbd6f1d042be4d6f1e1649855d864387eb8f0fd49c205c37790' 'd1874078516c1a05c74f67678456679ba7e05bb5aed7303c5aeeeba6e619accf702a'), (36, 'cb7e3668a97ef8ea55902658b62a682406f7206f75e5438ff95b4519fed1' 'e73e16ce5a29b4385fa2560820f0c8f42227709387dbad3a8208b57c381e268ffe38'), (63, '9e2d89afb0633c2f64b2eb4fdbba4663401ee673753a66d6d899e4a4101a' 'e4920b0b16f0e716e4f7d62d83b5784740c138ac6ab94fa14256ebb468e25f20e02f') ] for reg, value in tests: conn.expect('G' + hex(reg)[2:] + ',' + value, 'OK') for reg, value in tests: conn.expect('g' + hex(reg)[2:], value) # Read invalid register index conn.expect('g41', '') # Write invalid register index conn.expect('G41,12345678', '')
def filesystem(_, target): ''' Filesystem tests. This creates a filesystem image with the test file fstest.txt in it, the compiles the program fs.c to perform operations on it. The program will print 'PASS' if it is successful. ''' test_harness.build_program(['fs.c']) subprocess.check_output( [test_harness.BIN_DIR + 'mkfs', test_harness.WORK_DIR + '/fsimage.bin', 'fstest.txt'], stderr=subprocess.STDOUT) result = test_harness.run_program(target=target, block_device=test_harness.WORK_DIR + '/fsimage.bin') if 'PASS' not in result or 'FAIL' in result: raise test_harness.TestException( 'test program did not indicate pass\n' + result)
def run_cosimulation_test(source_file, *unused): random_seed = random.randint(0, 0xffffffff) if test_harness.DEBUG: print('random seed is {}'.format(random_seed)) verilator_args = [ test_harness.VSIM_PATH, '+trace', '+memdumpfile=' + VERILATOR_MEM_DUMP, '+memdumpbase=800000', '+memdumplen=400000', '+autoflushl2', '+verilator+rand+reset+2', '+verilator+seed+{}'.format(random_seed) ] # XXX this should probably be a command line option in test_harness.py if 'RANDSEED' in os.environ: verilator_args += ['+randseed=' + os.environ['RANDSEED']] emulator_args = [ test_harness.EMULATOR_PATH, '-m', 'cosim', '-d', EMULATOR_MEM_DUMP + ',0x800000,0x400000' ] if test_harness.DEBUG: emulator_args += ['-v'] hexfile = test_harness.build_program([source_file]) try: p1 = subprocess.Popen( verilator_args + ['+bin=' + hexfile], stdout=subprocess.PIPE) p2 = subprocess.Popen( emulator_args + [hexfile], stdin=p1.stdout, stdout=subprocess.PIPE) output = '' while True: got = p2.stdout.read(0x1000) if not got: break if test_harness.DEBUG: print(got.decode()) else: output += got.decode() p2.wait() time.sleep(1) # Give verilator a chance to clean up finally: p1.kill() p2.kill() if p2.returncode: raise test_harness.TestException( 'FAIL: cosimulation mismatch\n' + output) test_harness.assert_files_equal(VERILATOR_MEM_DUMP, EMULATOR_MEM_DUMP, 'final memory contents to not match')
def gdb_read_write_memory(_): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Read program code at address 0. This should match values # in count.hex conn.expect('m0,10', '0004800700088007000c800700108007') # (address, data) tests = [ (0x1000, '523c66b3'), (0x1234, '22'), (0x2242, '45f280397a5a3255fa19238693ff13c729'), (0x100000, '55483c091aac1e8c6db4bed1'), (0x200000, '16e1d56029e912a04121ce41a635155f3442355533703fafcb57f8295dd6330f82f9ffc40edb589fac1523665dc2f6e80c1e2de9718d253fcbce1c8a52c9dc21'), ] # Write memory for addr, data in tests: conn.expect('M' + hex(addr)[2:] + ',' + hex(int(len(data) / 2))[2:] + ':' + data, 'OK') # Read and verify for addr, data in tests: conn.expect('m' + hex(addr)[2:] + ',' + hex(int(len(data) / 2))[2:], data) # Try to write a bad address (out of range) # Doesn't return an error, test just ensures it # doesn't crash conn.expect('M10000000,4,12345678', 'OK') # Try to read a bad address (out of range) # As above, doesn't return error (returns 0xff...), # but ensure it doesn't crash. conn.expect('m10000000,4', 'ffffffff')
def run_csmith_test(_, target): # Find version of csmith result = subprocess.check_output(['csmith', '-v']).decode() got = VERSION_RE.search(result) if not got: raise test_harness.TestException( 'Could not determine csmith version ' + result) version_str = got.group('version') csmith_include = '-I/usr/local/include/csmith-' + version_str for x in range(100): source_file = 'test%04d.c' % x print('running ' + source_file) # Disable packed structs because we don't support unaligned accesses. # Disable longlong to avoid incompatibilities between 32-bit Nyuzi # and 64-bit hosts. subprocess.check_call(['csmith', '-o', source_file, '--no-longlong', '--no-packed-struct']) # Compile and run on host subprocess.check_call( ['cc', '-w', source_file, '-o', test_harness.WORK_DIR + '/a.out', csmith_include]) result = subprocess.check_output( test_harness.WORK_DIR + '/a.out').decode() got = CHECKSUM_RE.search(result) if not got: raise test_harness.TestException('no checksum in host output') host_checksum = int(got.group('checksum'), 16) print('host checksum %08x' % host_checksum) # Compile and run under emulator test_harness.build_program([source_file], cflags=[csmith_include]) result = test_harness.run_program(target) got = CHECKSUM_RE.search(result) if not got: raise test_harness.TestException('no checksum in host output') emulator_checksum = int(got.group('checksum'), 16) print('emulator checksum %08x' % emulator_checksum) if host_checksum != emulator_checksum: raise test_harness.TestException('checksum mismatch') print('PASS')
def gdb_select_thread(_, target): hexfile = test_harness.build_program(['multithreaded.S'], image_type='raw') with EmulatorProcess(hexfile, num_cores=2), DebugConnection() as conn: # Read thread ID conn.expect('qC', 'QC01') # Each line is one thread tests = [ (7, 0xc7733c56), (5, 0xf54adec3), (1, 0x5afaf01e), (2, 0x1964682e), (3, 0x16cc6be1), (8, 0xcbff923), (4, 0x4596de2), (6, 0xcd920ca6), ] # Step all threads through initialization code (5 instructions) for thid in range(len(tests)): # Switch to thread conn.expect('Hg' + str(thid + 1), 'OK') # Read thread ID conn.expect('qC', 'QC0' + str(thid + 1)) for index in range(5): conn.expect('S', 'S05') # Read PC register conn.expect('g40', '{:08x}'.format( test_harness.endian_swap((index + 1) * 4))) # Now all threads are at the same instruction: # 00000014 move s0, 1 # Step each thread independently some number of steps and # write a value to register 1 for index, (num_steps, regval) in enumerate(tests): conn.expect('Hg' + str(index + 1), 'OK') # Switch to thread for _ in range(num_steps): conn.expect('S', 'S05') conn.expect('G01,{:08x}'.format(regval), 'OK') # Read back PC and register values for index, (num_steps, regval) in enumerate(tests): conn.expect('Hg' + str(index + 1), 'OK') # Switch to thread conn.expect('g40', '{:08x}'.format( test_harness.endian_swap(0x14 + num_steps * 4))) conn.expect('g01', '{:08x}'.format(regval)) # Try to switch to an invalid thread ID conn.expect('Hgfe', '') # Ensure still on thread 8 conn.expect('qC', 'QC08')
def gdb_big_command(_, target): """ Check for buffer overflows by sending a very large command""" hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Big, invalid command. this should return an error (empty response) conn.expect('x' * 0x10000, '') # Now send a valid request to ensure it is still alive. conn.expect('qC', 'QC01')
def gdb_thread_info(_, target): # Run with one core, four threads hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: conn.expect('qfThreadInfo', 'm1,2,3,4') # Run with two cores, eight threads with EmulatorProcess(hexfile, num_cores=2), DebugConnection() as conn: conn.expect('qfThreadInfo', 'm1,2,3,4,5,6,7,8')
def dflush(_): test_harness.build_program(['dflush.S']) test_harness.run_program( environment='verilator', dump_file='obj/vmem.bin', dump_base=BASE_ADDRESS, dump_length=0x40000) with open('obj/vmem.bin', 'rb') as memfile: for index in range(4096): val = memfile.read(4) if len(val) < 4: raise test_harness.TestException('output file is truncated') num_val, = struct.unpack('<L', val) expected = 0x1f0e6231 + (index // 16) if num_val != expected: raise test_harness.TestException('FAIL: mismatch at ' + hex( BASE_ADDRESS + (index * 4)) + ' want ' + str(expected) + ' got ' + str(num_val))
def jtag_inject(*unused): """ Test instruction injection, with multiple threads """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Halt fixture.jtag_transfer(INST_CONTROL, 7, 0x1) # Load register values in thread 0 # First value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x3b643e9a) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000b2) # getcr s5, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) # Second value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xd1dc20a3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000d2) # getcr s6, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) # Load register values in thread 1 fixture.jtag_transfer(INST_CONTROL, 7, 0x3) # First value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xa6532328) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000b2) # getcr s5, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) # Second value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xf01839a0) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000d2) # getcr s6, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) # Perform operation on thread 0 fixture.jtag_transfer(INST_CONTROL, 7, 0x1) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xc03300e5) # xor s7, s5, s6 fixture.jtag_transfer(INST_SAME, 32, 0x8c0000f2) # setcr s7, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0xeab81e39) # Perform operation on thread 1 fixture.jtag_transfer(INST_CONTROL, 7, 0x3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xc03300e5) # xor s7, s5, s6 fixture.jtag_transfer(INST_SAME, 32, 0x8c0000f2) # setcr s7, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0x564b1a88)
def atomic(_, target): test_harness.build_program(['atomic.S']) test_harness.run_program( target=target, dump_file=test_harness.WORK_DIR + '/vmem.bin', dump_base=0x100000, dump_length=0x800, flush_l2=True) with open(test_harness.WORK_DIR + '/vmem.bin', 'rb') as memfile: for _ in range(512): val = memfile.read(4) if len(val) < 4: raise test_harness.TestException('output file is truncated') num_val, = struct.unpack('<L', val) if num_val != 10: raise test_harness.TestException( 'FAIL: mismatch: ' + str(num_val))
def jtag_bypass(*unused): """ Validate BYPASS instruction, which is a single bit data register We should get what we send, shifted by one bit. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: value = 0x267521cf fixture.jtag_transfer(INST_BYPASS, 32, value) fixture.expect_data(value << 1)
def dinvalidate(_): test_harness.build_program(['dinvalidate.S']) result = test_harness.run_program( environment='verilator', dump_file='obj/vmem.bin', dump_base=0x2000, dump_length=4, flush_l2=True, trace=True) # 1. Check that the proper value was read into s2 if '02 deadbeef' not in result: raise test_harness.TestException( 'incorrect value was written back ' + result) # 2. Read the memory dump to ensure the proper value is flushed from the # L2 cache with open('obj/vmem.bin', 'rb') as memfile: num_val, = struct.unpack('<L', memfile.read(4)) if num_val != 0xdeadbeef: raise test_harness.TestException( 'memory contents were incorrect: ' + hex(num_val))
def dinvalidate(_, target): test_harness.build_program(['dinvalidate.S']) result = test_harness.run_program( target=target, dump_file='obj/vmem.bin', dump_base=0x2000, dump_length=4, flush_l2=True, trace=True) # 1. Check that the proper value was read into s2 if '02 deadbeef' not in result: raise test_harness.TestException( 'incorrect value was written back ' + result) # 2. Read the memory dump to ensure the proper value is flushed from the # L2 cache with open('obj/vmem.bin', 'rb') as memfile: num_val, = struct.unpack('<L', memfile.read(4)) if num_val != 0xdeadbeef: raise test_harness.TestException( 'memory contents were incorrect: ' + hex(num_val))
def jtag_instruction_shift(*unused): """Ensure instruction bits shifted into TDI come out TDO. This is necessary to properly chain JTAG devices together. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: fixture.test_instruction_shift(0xf) fixture.test_instruction_shift(0xa) fixture.test_instruction_shift(0x5) fixture.test_instruction_shift(0x3) fixture.test_instruction_shift(0xc) fixture.test_instruction_shift(0)
def gdb_vcont(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Set breakpoint conn.expect('Z0,00000010', 'OK') # Step conn.expect('vCont;s:0001', 'S05') conn.expect('g40', '04000000') # Continue conn.expect('vCont;c', 'S05') conn.expect('g40', '10000000')
def recv_host_interrupt(*unused): try: os.remove(RECV_PIPE_NAME) except OSError: pass # Ignore if pipe doesn't exist test_harness.build_program(['recv_host_interrupt.S']) os.mknod(RECV_PIPE_NAME, stat.S_IFIFO | 0o666) args = [ test_harness.EMULATOR_PATH, '-i', RECV_PIPE_NAME, test_harness.HEX_FILE ] emulator_process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) try: interrupt_pipe = os.open(RECV_PIPE_NAME, os.O_WRONLY) # Send periodic interrupts to process try: for intnum in range(5): os.write(interrupt_pipe, str.encode(chr(intnum))) time.sleep(0.2) except OSError: # Broken pipe will occur if the emulator exits early. # We'll flag an error after communicate if we don't see a PASS. pass # Wait for completion result, _ = test_harness.TimedProcessRunner().communicate( emulator_process, 60) strresult = str(result) if 'PASS' not in strresult or 'FAIL' in strresult: raise test_harness.TestException('Test failed ' + strresult) finally: os.close(interrupt_pipe) os.unlink(RECV_PIPE_NAME)
def jtag_instruction_shift(*unused): """ Ensure instruction bits shifted into TDI come out TDO. This is necessary to properly chain JTAG devices together. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: fixture.test_instruction_shift(0xf) fixture.test_instruction_shift(0xa) fixture.test_instruction_shift(0x5) fixture.test_instruction_shift(0x3) fixture.test_instruction_shift(0xc) fixture.test_instruction_shift(0)
def run_io_interrupt(name): underscore = name.rfind('_') if underscore == -1: raise test_harness.TestException( 'Internal error: run_io_interrupt did not have type') environment = name[underscore + 1:] test_harness.build_program(['io_interrupt.S']) result = test_harness.run_program(environment=environment) lines = result.split('\n') output = None for line in lines: start = line.find('!') if start != -1: output = line[start + 1:] if output is None: raise test_harness.TestException('Could not find output string:\n' + result) # Make sure enough interrupts were triggered if output.count('*') < 2: raise test_harness.TestException('Not enough interrupts triggered:\n' + result) # Make sure we see at least some of the base string printed after an # interrupt if output.find('*') >= len(output) - 1: raise test_harness.TestException( 'No instances of interrupt return:\n' + result) # Remove all asterisks (interrupts) and make sure string is intact stripped = output.replace('*', '') if stripped != '0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`' \ 'abcdefghijklmnopqrstuvwxyz' * 10: raise test_harness.TestException('Base string does not match:\n' + stripped)
def jtag_data_transfer(*unused): """Validate bi-directional transfer. The TRANSFER_DATA instruction returns the old value of the control register while shifting a new one in, so we should see the previous value come out each time we write a new one. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x4be49e7c) fixture.jtag_transfer(INST_SAME, 32, 0xb282dc16) fixture.expect_data(0x4be49e7c) fixture.jtag_transfer(INST_SAME, 32, 0x7ee4838) fixture.expect_data(0xb282dc16)
def jtag_idcode(*unused): """ Validate response to IDCODE request """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Ensure the default instruction after reset is IDCODE fixture.jtag_transfer(INST_SAME, 32, 0xffffffff) fixture.expect_data(EXPECTED_IDCODE) # Explicitly shift the IDCODE instruction to make sure it is # correct. fixture.jtag_transfer(INST_IDCODE, 32, 0xffffffff) fixture.expect_data(EXPECTED_IDCODE)
def gdb_queries(_, target): """Miscellaneous query commands not covered in other tests""" hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: conn.expect('qLaunchSuccess', 'OK') conn.expect('qHostInfo', 'triple:nyuzi;endian:little;ptrsize:4') conn.expect('qProcessInfo', 'pid:1') conn.expect('qsThreadInfo', 'l') # No active threads conn.expect('qThreadStopInfo', 'S00') conn.expect('qC', 'QC01') # Should be invalid conn.expect('qZ', '')
def run_cosimulation_test(source_file, *unused): verilator_args = [ test_harness.VSIM_PATH, '+trace', '+memdumpfile=' + VERILATOR_MEM_DUMP, '+memdumpbase=800000', '+memdumplen=400000', '+autoflushl2' ] # XXX this should probably be a command line option in test_harness.py if 'RANDSEED' in os.environ: verilator_args += ['+randseed=' + os.environ['RANDSEED']] emulator_args = [ test_harness.EMULATOR_PATH, '-m', 'cosim', '-d', EMULATOR_MEM_DUMP + ',0x800000,0x400000' ] if test_harness.DEBUG: emulator_args += ['-v'] hexfile = test_harness.build_program([source_file]) p1 = subprocess.Popen( verilator_args + ['+bin=' + hexfile], stdout=subprocess.PIPE) p2 = subprocess.Popen( emulator_args + [hexfile], stdin=p1.stdout, stdout=subprocess.PIPE) output = '' while True: got = p2.stdout.read(0x1000) if not got: break if test_harness.DEBUG: print(got.decode()) else: output += got.decode() p2.wait() time.sleep(1) # Give verilator a chance to clean up test_harness.kill_gently(p2) # Make sure verilator has exited if p2.returncode: raise test_harness.TestException( 'FAIL: cosimulation mismatch\n' + output) test_harness.assert_files_equal(VERILATOR_MEM_DUMP, EMULATOR_MEM_DUMP, 'final memory contents to not match')
def jtag_reset(*unused): """Test transition to reset state.""" hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Load a different instruction fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x3b643e9a) # Perform a reset (setting zero lengths) fixture.jtag_transfer(INST_SAME, 0, 0) # Perform data-only transfer. Ensure we get the idcode back. # If we hadn't performed a reset, we would get data value # that was shifted above. fixture.jtag_transfer(INST_SAME, 32, 0xffffffff) fixture.expect_data(EXPECTED_IDCODE)
def sdmmc_read(_, target): # Create random file with open(SOURCE_BLOCK_DEV, 'wb') as fsimage: fsimage.write(os.urandom(FILE_SIZE)) hex_file = test_harness.build_program(['sdmmc_read.c']) test_harness.run_program(hex_file, target, block_device=SOURCE_BLOCK_DEV, dump_file=MEMDUMP, dump_base=0x200000, dump_length=FILE_SIZE, flush_l2=True) test_harness.assert_files_equal(SOURCE_BLOCK_DEV, MEMDUMP, 'file mismatch')
def gdb_breakpoint_errors(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Set invalid breakpoint (memory out of range) conn.expect('Z0,20000000', '') # Set invalid breakpoint (unaligned) conn.expect('Z0,00000003', '') # Set a valid breakpoint, then try to set the same address again conn.expect('Z0,00000008', 'OK') conn.expect('Z0,00000008', '') # Remove invalid breakpoint (doesn't exist) conn.expect('z0,00000004', '')
def run_csmith_test(_, target): # Find version of csmith result = subprocess.check_output(['csmith', '-v']).decode() got = VERSION_RE.search(result) if not got: raise test_harness.TestException( 'Could not determine csmith version ' + result) version_str = got.group('version') csmith_include = '-I/usr/local/include/csmith-' + version_str for x in range(100): source_file = os.path.join(test_harness.WORK_DIR, 'test%04d.c' % x) print('running ' + source_file) # Disable packed structs because we don't support unaligned accesses. # Disable longlong to avoid incompatibilities between 32-bit Nyuzi # and 64-bit hosts. subprocess.check_call([ 'csmith', '-o', source_file, '--no-longlong', '--no-packed-struct' ]) # Compile and run on host subprocess.check_call( ['cc', '-w', source_file, '-o', HOST_EXE, csmith_include]) result = subprocess.check_output(HOST_EXE).decode() got = CHECKSUM_RE.search(result) if not got: raise test_harness.TestException('no checksum in host output') host_checksum = int(got.group('checksum'), 16) print('host checksum %08x' % host_checksum) # Compile and run under emulator hex_file = test_harness.build_program([source_file], cflags=[csmith_include]) result = test_harness.run_program(hex_file, target) got = CHECKSUM_RE.search(result) if not got: raise test_harness.TestException('no checksum in host output') emulator_checksum = int(got.group('checksum'), 16) print('emulator checksum %08x' % emulator_checksum) if host_checksum != emulator_checksum: raise test_harness.TestException('checksum mismatch') print('PASS')
def jtag(_): hexfile = test_harness.build_program(['test_program.S']) with VerilatorProcess(hexfile), DebugConnection() as conn: conn.jtag_transfer(4, INST_CONTROL, 7, 0x1) conn.jtag_transfer(4, INST_WRITE_DATA, 32, 0x3b643e9a) # First value to transfer conn.jtag_transfer(4, INST_INJECT_INST, 32, 0xac0000b2) # getcr s5, 18 conn.jtag_transfer(4, INST_WRITE_DATA, 32, 0xd1dc20a3) # Second value to transfer conn.jtag_transfer(4, INST_INJECT_INST, 32, 0xac0000d2) # getcr s6, 18 conn.jtag_transfer(4, INST_INJECT_INST, 32, 0xc03300e5) # xor s7, s5, s6 conn.jtag_transfer(4, INST_INJECT_INST, 32, 0x8c0000f2) # setcr s7, 18 if conn.jtag_transfer(4, INST_READ_DATA, 32, 0) != 0xeab81e39: raise test_harness.TestException('read value mismatch')
def jtag_read_write_pc(*unused): """Use the call instruction to read the program counter. The injection logic is supposed to simulate each instruction having the PC of the interrupted thread. Then ensure performing a branch will properly update the PC of the selected thread. This then resumes the thread to ensure it operates properly. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Switch to thread 1, branch to new address fixture.jtag_transfer(INST_CONTROL, 7, 0x3) fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x10e4) # `jump_target` fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac000012) # getcr s0, 18 fixture.jtag_transfer(INST_SAME, 32, 0xf0000000) # b s0 # Switch to thread 0, read PC to ensure it is read correctly # and that the branch didn't affect it. # (the return address will be the branch location + 4) fixture.jtag_transfer(INST_CONTROL, 7, 0x1) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xf8000000) # call 0 fixture.jtag_transfer(INST_SAME, 32, 0x8c0003f2) # setcr ra, 18 fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0x10d8) # Switch back to thread 1, read back PC to ensure it is in the new # location fixture.jtag_transfer(INST_CONTROL, 7, 0x3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xf8000000) # call 0 fixture.jtag_transfer(INST_SAME, 32, 0x8c0003f2) # setcr ra, 18 fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0x10e8) # Resume the thread. It should now execute the instruction to # load a new value into s0 fixture.jtag_transfer(INST_CONTROL, 7, 0x0) # Dummy transaction that ensures the processor has time to execute # the instructions fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) # Halt again and verify register value. fixture.jtag_transfer(INST_CONTROL, 7, 0x3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0x8c000012) # setcr s0, 18 fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0x6bee68ca)
def uart_echo_test(*unused): ''' The emulator direct all UART traffic through the terminal that it is launched from. This validates transfers in both directions. ''' executable = test_harness.build_program(['uart_echo_test.c']) args = [test_harness.EMULATOR_PATH, executable] in_str = 'THE QUICK brOwn FOX jumPED Over THE LAZY DOG\n' process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) out_str, _ = test_harness.TimedProcessRunner().communicate( process=process, timeout=10, input=in_str.encode('ascii')) out_str = out_str.decode() if 'the quick brown fox jumped over the lazy dog' not in out_str: raise test_harness.TestException( 'Subprocess returned incorrect result \"' + out_str + '"')
def dflush(_, target): hex_file = test_harness.build_program(['dflush.S']) test_harness.run_program(hex_file, target, dump_file=MEM_DUMP_FILE, dump_base=BASE_ADDRESS, dump_length=0x40000) with open(MEM_DUMP_FILE, 'rb') as memfile: for index in range(4096): val = memfile.read(4) if len(val) < 4: raise test_harness.TestException('output file is truncated') num_val, = struct.unpack('<L', val) expected = 0x1f0e6231 + (index // 16) if num_val != expected: raise test_harness.TestException( 'FAIL: mismatch at 0x{:x} want {} got {}'.format( BASE_ADDRESS + (index * 4), expected, num_val))
def jtag_inject_rollback(_, target): """ Test reading status register. I put in an instruction that will miss the cache, so I know it will roll back. """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Halt fixture.jtag_transfer(INST_CONTROL, 7, 0x1) # Load register values in thread 0 # First value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x10000) # High address, not cached fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac000012) # getcr s0, 18 fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_READY) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xa8000000) # load_32 s0, (s0) fixture.jtag_transfer(INST_STATUS, 2, 0) fixture.expect_data(STATUS_ROLLED_BACK)
def filesystem(_, target): """Test the filesystem implementation in libos. This creates a filesystem image with the test file fstest.txt in it, the compiles the program fs.c to perform operations on it. The program will print 'PASS' if it is successful. """ hex_file = test_harness.build_program(['fs.c']) subprocess.check_output([ os.path.join(test_harness.TOOL_BIN_DIR, 'mkfs'), FS_IMAGE_PATH, 'fstest.txt' ], stderr=subprocess.STDOUT) result = test_harness.run_program(hex_file, target, block_device=FS_IMAGE_PATH) if 'PASS' not in result or 'FAIL' in result: raise test_harness.TestException( 'test program did not indicate pass\n' + result)
def atomic(_, target): hex_file = test_harness.build_program(['atomic.S']) test_harness.run_program( hex_file, target, dump_file=MEM_DUMP_FILE, dump_base=0x100000, dump_length=0x800, flush_l2=True) with open(MEM_DUMP_FILE, 'rb') as memfile: for _ in range(512): val = memfile.read(4) if len(val) < 4: raise test_harness.TestException('output file is truncated') num_val, = struct.unpack('<L', val) if num_val != 10: raise test_harness.TestException( 'FAIL: mismatch: ' + str(num_val))
def gdb_remove_breakpoint(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Set breakpoint conn.expect('Z0,0000000c', 'OK') # Set second breakpoint conn.expect('Z0,00000014', 'OK') # Clear first breakpoint conn.expect('z0,0000000c', 'OK') # Continue conn.expect('C', 'S05') # Read PC register. Should be at second breakpoint conn.expect('g40', '14000000') # Read s0, which should be 5 conn.expect('g00', '05000000')
def jtag_inject(_, target): """ Test instruction injection, with multiple threads """ hexfile = test_harness.build_program(['test_program.S']) with JTAGTestFixture(hexfile) as fixture: # Halt fixture.jtag_transfer(INST_CONTROL, 7, 0x1) # Load register values in thread 0 # First value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0x3b643e9a) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000b2) # getcr s5, 18 # Second value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xd1dc20a3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000d2) # getcr s6, 18 # Load register values in thread 1 fixture.jtag_transfer(INST_CONTROL, 7, 0x3) # First value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xa6532328) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000b2) # getcr s5, 18 # Second value to transfer fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0xf01839a0) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xac0000d2) # getcr s6, 18 # Perform operation on thread 0 fixture.jtag_transfer(INST_CONTROL, 7, 0x1) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xc03300e5) # xor s7, s5, s6 fixture.jtag_transfer(INST_SAME, 32, 0x8c0000f2) # setcr s7, 18 fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0xeab81e39) # Perform operation on thread 1 fixture.jtag_transfer(INST_CONTROL, 7, 0x3) fixture.jtag_transfer(INST_INJECT_INST, 32, 0xc03300e5) # xor s7, s5, s6 fixture.jtag_transfer(INST_SAME, 32, 0x8c0000f2) # setcr s7, 18 fixture.jtag_transfer(INST_TRANSFER_DATA, 32, 0) fixture.expect_data(0x564b1a88)
def profile(*unused): hexfile = test_harness.build_program(['test_program.c']) # XXX hack: this is currently not returned from build_program, but I # know what the name is. elffile = hexfile.replace('.hex', '.elf') profile_file = os.path.join(test_harness.WORK_DIR, 'profile.out') test_harness.run_program(hexfile, 'verilator', profile_file=profile_file) symbol_file = os.path.join(test_harness.WORK_DIR, 'symbols.txt') objdump_args = [ os.path.join(test_harness.COMPILER_BIN_DIR, 'llvm-objdump'), '-t', elffile ] symbols = subprocess.check_output(objdump_args) with open(symbol_file, 'w') as f: f.write(symbols.decode()) profile_args = [ os.path.join(test_harness.TOOL_BIN_DIR, 'profile.py'), symbol_file, profile_file ] profile_output = subprocess.check_output(' '.join(profile_args), shell=True) profile_lines = profile_output.decode().split('\n') profile_tuples = [line.split() for line in profile_lines if line] profile_map = {func: int(count) for count, _, func in profile_tuples} # These tests don't end up being exactly 2x the number of samples. Because # the system samples randomly, it can vary. I could have ran the test longer # to get more samples, but this is really just a smoke test and I didn't want # to bloat the test time unnecessarily. loop5k = profile_map['loop5000'] loop10k = profile_map['loop10000'] loop20k = profile_map['loop20000'] test_harness.assert_greater(loop5k, 0) test_harness.assert_greater(loop10k, loop5k * 1.75) test_harness.assert_greater(loop20k, loop10k * 1.75)
def gdb_single_step_breakpoint(_, target): """ Ensure that if you single step through a breakpoint, it doesn't trigger and get stuck """ hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Set breakpoint at second instruction (address 0x8) conn.expect('Z0,00000004', 'OK') # Single step over first instruction conn.expect('S', 'S05') # Single step. This one has a breakpoint, but we won't # stop at it. conn.expect('S', 'S05') # Read PC register conn.expect('g40', '08000000') # Read s0 conn.expect('g00', '02000000')
def gdb_read_write_register(_, target): hexfile = test_harness.build_program(['register_values.S']) with EmulatorProcess(hexfile), DebugConnection() as conn: # Run code to load registers conn.expect('C', 'S05') # Check values set by program (remote GDB returns in swapped byte # order...) conn.expect('g1', '7d7f3e85') conn.expect( 'g20', 'f13403ef9d08309993f7819954ae4b3f7aeaa28f538fecbd95' '36f59c6d7251269525ee70d26e8d34f48912639c86ae5dba426c83aa8455e1e2dbba4b41a4f321' ) tests = [ (0, 'd3839b18'), (1, '7b53cc78'), (30, '0904c47d'), (32, 'aef331bc7dbd6f1d042be4d6f1e1649855d864387eb8f0fd49c205c37790' 'd1874078516c1a05c74f67678456679ba7e05bb5aed7303c5aeeeba6e619accf702a' ), (36, 'cb7e3668a97ef8ea55902658b62a682406f7206f75e5438ff95b4519fed1' 'e73e16ce5a29b4385fa2560820f0c8f42227709387dbad3a8208b57c381e268ffe38' ), (63, '9e2d89afb0633c2f64b2eb4fdbba4663401ee673753a66d6d899e4a4101a' 'e4920b0b16f0e716e4f7d62d83b5784740c138ac6ab94fa14256ebb468e25f20e02f' ) ] for reg, value in tests: conn.expect('G' + hex(reg)[2:] + ',' + value, 'OK') for reg, value in tests: conn.expect('g' + hex(reg)[2:], value) # Read invalid register index conn.expect('g41', '') # Write invalid register index conn.expect('G41,12345678', '')
def gdb_read_write_memory(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Read program code at address 0. This should match values # in count.hex conn.expect('m0,10', '0004000f0008000f000c000f0010000f') # (address, data) tests = [ (0x1000, '523c66b3'), (0x1234, '22'), (0x2242, '45f280397a5a3255fa19238693ff13c729'), (0x100000, '55483c091aac1e8c6db4bed1'), (0x200000, '16e1d56029e912a04121ce41a635155f3442355533703fafcb57f8' '295dd6330f82f9ffc40edb589fac1523665dc2f6e80c1e2de9718d253fcbc' 'e1c8a52c9dc21'), ] # Write memory for addr, data in tests: conn.expect( 'M' + hex(addr)[2:] + ',' + hex(int(len(data) / 2))[2:] + ':' + data, 'OK') # Read and verify for addr, data in tests: conn.expect( 'm' + hex(addr)[2:] + ',' + hex(int(len(data) / 2))[2:], data) # Try to write a bad address (out of range) # Doesn't return an error, test just ensures it # doesn't crash conn.expect('M10000000,4,12345678', 'OK') # Try to read a bad address (out of range) # As above, doesn't return error (returns 0xff...), # but ensure it doesn't crash. conn.expect('m10000000,4', 'ffffffff')
def gdb_single_step(_, target): hexfile = test_harness.build_program(['count.S'], image_type='raw') with EmulatorProcess(hexfile), DebugConnection() as conn: # Read PC register conn.expect('g40', '00000000') # Single step conn.expect('S', 'S05') # Read PC register conn.expect('g40', '04000000') # Read s0 conn.expect('g00', '01000000') # Single step (note here I use the lowercase version) conn.expect('s', 'S05') # Read PC register conn.expect('g40', '08000000') # Read s0 conn.expect('g00', '02000000')
def perf_counters(_): test_harness.build_program(['perf_counters.c']) result = test_harness.run_program(environment='verilator') if 'PASS' not in result: raise test_harness.TestException( 'test program did not indicate pass\n' + result)
def run_emulator_test(source_file): test_harness.build_program([source_file]) result = test_harness.run_program(environment='emulator') test_harness.check_result(source_file, result)
def ps2(_, target): test_harness.build_program(['ps2.c']) result = test_harness.run_program(target) if 'PASS' not in result: raise test_harness.TestException('program did not indicate pass\n' + result)