| """ Tool for reading bram test output and outputting human readable output. | 
 |  | 
 | """ | 
 | import argparse | 
 | import serial | 
 | from collections import deque, namedtuple | 
 | import struct | 
 | import itertools | 
 | import enum | 
 |  | 
 |  | 
 | class RamTestState(enum.Enum): | 
 |     START = 1 | 
 |     VERIFY_INIT = 2 | 
 |     WRITE_ZEROS = 3 | 
 |     VERIFY_ZEROS = 4 | 
 |     WRITE_ONES = 5 | 
 |     VERIFY_ONES = 6 | 
 |     WRITE_10 = 7 | 
 |     VERIFY_10 = 8 | 
 |     WRITE_01 = 9 | 
 |     VERIFY_01 = 10 | 
 |     WRITE_RANDOM = 11 | 
 |     VERIFY_RANDOM = 12 | 
 |     RESTART_LOOP = 13 | 
 |  | 
 |  | 
 | Result = namedtuple('Results', 'error_count loop_count') | 
 | Error = namedtuple('Error', 'state address expected_value actual_value') | 
 |  | 
 | RESULT_LOG = '<BBHBB' | 
 | RESULT_LOG_SIZE = struct.calcsize(RESULT_LOG) | 
 |  | 
 | ERROR_LOG = '<BBHHHBB' | 
 | ERROR_LOG_SIZE = struct.calcsize(ERROR_LOG) | 
 |  | 
 |  | 
 | def process_buffer(data): | 
 |     while data: | 
 |         while data: | 
 |             first_char = bytes((data[0], )) | 
 |             if first_char in [b'E', b'L']: | 
 |                 break | 
 |  | 
 |             data.popleft() | 
 |  | 
 |         if not data: | 
 |             return | 
 |  | 
 |         first_char = bytes((data[0], )) | 
 |  | 
 |         if first_char == b'L' and len(data) >= RESULT_LOG_SIZE: | 
 |             log = bytes(itertools.islice(data, 0, RESULT_LOG_SIZE)) | 
 |             data.popleft() | 
 |  | 
 |             header, error_count, loop_count, cr, lf = struct.unpack( | 
 |                 RESULT_LOG, log | 
 |             ) | 
 |  | 
 |             if cr == ord('\r') and lf == ord('\n'): | 
 |                 yield Result(error_count=error_count, loop_count=loop_count) | 
 |  | 
 |         elif first_char == b'E' and len(data) >= ERROR_LOG_SIZE: | 
 |             log = bytes(itertools.islice(data, 0, ERROR_LOG_SIZE)) | 
 |             data.popleft() | 
 |  | 
 |             header, state, address, expected_value, actual_value, cr, lf = struct.unpack( | 
 |                 ERROR_LOG, log | 
 |             ) | 
 |  | 
 |             if cr == ord('\r') and lf == ord('\n'): | 
 |                 try: | 
 |                     state = RamTestState(state) | 
 |                 except Exception: | 
 |                     continue | 
 |  | 
 |                 yield Error( | 
 |                     state=RamTestState(state), | 
 |                     address=hex(address), | 
 |                     expected_value=hex(expected_value), | 
 |                     actual_value=hex(actual_value) | 
 |                 ) | 
 |         else: | 
 |             return | 
 |  | 
 |  | 
 | def main(): | 
 |     parser = argparse.ArgumentParser(description=__doc__) | 
 |  | 
 |     parser.add_argument('uart') | 
 |     parser.add_argument('--file', action='store_true') | 
 |     parser.add_argument('--baudrate', '-B', type=int, default=500000) | 
 |  | 
 |     args = parser.parse_args() | 
 |  | 
 |     if args.file: | 
 |         with open(args.uart, 'rb') as f: | 
 |             data = deque(f.read()) | 
 |             for log in process_buffer(data): | 
 |                 print(log) | 
 |     else: | 
 |         data = deque() | 
 |         with serial.Serial(port=args.uart, baudrate=args.baudrate, | 
 |                            timeout=.200, inter_byte_timeout=.200) as s: | 
 |             while True: | 
 |                 buf = s.read(10 * 1024) | 
 |                 data.extend(buf) | 
 |  | 
 |                 for log in process_buffer(data): | 
 |                     print(log) | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |     main() |