From 257dbc749f6513e12dbc1edb5926af9c89f68264 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 22 Feb 2019 11:40:44 -0800 Subject: [PATCH] CPLD: Checksum tool. --- firmware/tools/cpld_crc.py | 321 +++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100755 firmware/tools/cpld_crc.py diff --git a/firmware/tools/cpld_crc.py b/firmware/tools/cpld_crc.py new file mode 100755 index 00000000..0a3dd601 --- /dev/null +++ b/firmware/tools/cpld_crc.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 + +import struct + +class DumbCRC32(object): + def __init__(self): + self._remainder = 0xffffffff + self._reversed_polynomial = 0xedb88320 + self._final_xor = 0xffffffff + + def update(self, data): + bit_count = len(data) * 8 + for bit_n in range(bit_count): + bit_in = data[bit_n >> 3] & (1 << (bit_n & 7)) + self._remainder ^= 1 if bit_in != 0 else 0 + bit_out = (self._remainder & 1) + self._remainder >>= 1; + if bit_out != 0: + self._remainder ^= self._reversed_polynomial; + + def digest(self): + return self._remainder ^ self._final_xor + + def hexdigest(self): + return '%08x' % self.digest() + +class XSVFParser(object): + def __init__(self): + self._handlers = { + 0x00: self.XCOMPLETE , + 0x01: self.XTDOMASK , + 0x02: self.XSIR , + 0x03: self.XSDR , + 0x04: self.XRUNTEST , + 0x07: self.XREPEAT , + 0x08: self.XSDRSIZE , + 0x09: self.XSDRTDO , + 0x0a: self.XSETSDRMASKS, + 0x0b: self.XSDRINC , + 0x0c: self.XSDRB , + 0x0d: self.XSDRC , + 0x0e: self.XSDRE , + 0x0f: self.XSDRTDOB , + 0x10: self.XSDRTDOC , + 0x11: self.XSDRTDOE , + 0x12: self.XSTATE , + 0x13: self.XENDIR , + 0x14: self.XENDDR , + 0x15: self.XSIR2 , + 0x16: self.XCOMMENT , + 0x17: self.XWAIT , + } + + def read_byte(self): + return self.read_bytes(1)[0] + + def read_bytes(self, n): + c = self._f.read(n) + if len(c) == n: + return c + else: + raise RuntimeError('unexpected end of file') + + def read_bits(self, n): + length_bytes = (n + 7) >> 3 + return self.read_bytes(length_bytes) + + def read_u32(self): + return struct.unpack('>I', self.read_bytes(4))[0] + + def parse(self, f, debug=False): + self._f = f + self._debug = debug + self._xcomplete = False + self._xenddr = None + self._xendir = None + self._xruntest = 0 + self._xsdrsize = None + self._xtdomask = None + self._commands = [] + + while self._xcomplete == False: + self.read_instruction() + + self._f = None + + return self._commands + + def read_instruction(self): + instruction_id = self.read_byte() + if instruction_id in self._handlers: + instruction_handler = self._handlers[instruction_id] + result = instruction_handler() + if result is not None: + self._commands.append(result) + else: + raise RuntimeError('unexpected instruction 0x%02x' % instruction_id) + + def XCOMPLETE(self): + self._xcomplete = True + + def XTDOMASK(self): + length_bits = self._xsdrsize + self._xtdomask = self.read_bits(length_bits) + + def XSIR(self): + length_bits = self.read_byte() + tdi = self.read_bits(length_bits) + if self._debug: + print('XSIR tdi=%d:%s' % (length_bits, tdi.hex())) + return { + 'type': 'xsir', + 'tdi': { + 'length': length_bits, + 'data': tdi + }, + } + + def XSDR(self): + length_bits = self._xsdrsize + tdi = self.read_bits(length_bits) + if self._debug: + print('XSDR tdi=%d:%s' % (length_bits, tdi.hex())) + return { + 'type': 'xsdr', + 'tdi': { + 'length': length_bits, + 'data': tdi, + }, + } + + def XRUNTEST(self): + self._xruntest = self.read_u32() + if self._debug: + print('XRUNTEST number=%d' % self._xruntest) + + def XREPEAT(self): + repeat = self.read_byte() + # print('XREPEAT times=%d' % repeat) + + def XSDRSIZE(self): + self._xsdrsize = self.read_u32() + + def XSDRTDO(self): + length_bits = self._xsdrsize + tdi = self.read_bits(length_bits) + tdo_mask = self._xtdomask + self._tdo_expected = (length_bits, self.read_bits(length_bits)) + wait = self._xruntest + if wait == 0: + end_state = self._xenddr + else: + end_state = 1 # Run-Test/Idle + if self._debug: + print('XSDRTDO tdi=%d:%s tdo_mask=%d:%s tdo_expected=%d:%s end_state=%u wait=%u' % ( + length_bits, tdi.hex(), + length_bits, tdo_mask.hex(), + self._tdo_expected[0], self._tdo_expected[1].hex(), + end_state, + wait, + )) + return { + 'type': 'xsdrtdo', + 'tdi': { + 'length': length_bits, + 'data': tdi + }, + 'tdo_mask': { + 'length': length_bits, + 'data': tdo_mask, + }, + 'tdo_expected': { + 'length': self._tdo_expected[0], + 'data': self._tdo_expected[1], + }, + 'end_state': end_state, + 'wait': wait, + } + + def XSETSDRMASKS(self): + raise RuntimeError('unimplemented') + + def XSDRINC(self): + raise RuntimeError('unimplemented') + + def XSDRB(self): + raise RuntimeError('unimplemented') + + def XSDRC(self): + raise RuntimeError('unimplemented') + + def XSDRE(self): + raise RuntimeError('unimplemented') + + def XSDRTDOB(self): + raise RuntimeError('unimplemented') + + def XSDRTDOC(self): + raise RuntimeError('unimplemented') + + def XSDRTDOE(self): + raise RuntimeError('unimplemented') + + def XSTATE(self): + state = self.read_byte() + if self._debug: + print('XSTATE %u' % state) + return { + 'type': 'xstate', + 'state': state, + } + + def XENDIR(self): + self._xendir = self.read_byte() + + def XENDDR(self): + self._xenddr = self.read_byte() + + def XSIR2(self): + raise RuntimeError('unimplemented') + + def XCOMMENT(self): + raise RuntimeError('unimplemented') + + def XWAIT(self): + wait_state = self.read_byte() + end_state = self.read_byte() + wait_time = self.read_u32() + +####################################################################### +# Command line argument parsing. +####################################################################### + +import sys + +if len(sys.argv) != 2: + print("Usage: cpld_crc.py