From 748b88e71e970dcda9c39c6c394c079cb6df90a8 Mon Sep 17 00:00:00 2001 From: Triss Date: Wed, 1 Jun 2022 16:48:02 +0200 Subject: [PATCH] svd diffing --- dvf/dvfparse.py | 20 +-- svd/svd.py | 377 +++++++++++++++++++++++++++++++++--------------- svd/svdparse.py | 16 +- 3 files changed, 281 insertions(+), 132 deletions(-) diff --git a/dvf/dvfparse.py b/dvf/dvfparse.py index 37dc95a..3a3eb02 100644 --- a/dvf/dvfparse.py +++ b/dvf/dvfparse.py @@ -197,16 +197,16 @@ class Dvf(NamedTuple): MCU_RL78x2y = 0x30 IDK_KNOWN_78K0 = { - b'\0\01\x02!\x02\0\0H\x11', # Kx2 - b'\0\01\x02\0\x01\0\0H\x11', # Kx2-A, uPD78F8039 - b'\0\01\x02\x01\x01\0\0H\x11', # Fx2 - b'\0\01\x02\x01\x02\0\0H\x11', # Kx2-L - b'\0\01\x02\x10\x01\0\0H\x11', # misc (Ix2, KC2-A, uPD78F0730) - b'\0\01\x02\x11\x01\0\0H\x11', # FC2 - b'\0\01\x02\x12\x01\0\0H\x11', # Lx3 - b'\0\02\x02\0\x01\0\0H\x11', # misc (uPD78F8077, Dx2, Kx2-C, uPD78F8039) - b'\0\02\x02\x02\x01\0\0H\x11', # Fx2-L - b'\0\02\x02\x10\x01\0\0H\x11', # Lx3-M + b'\0\x001\x02!\x02\0\0H\x11', # Kx2 + b'\0\x001\x02\0\x01\0\0H\x11', # Kx2-A, uPD78F8039 + b'\0\x001\x02\x01\x01\0\0H\x11', # Fx2 + b'\0\x001\x02\x01\x02\0\0H\x11', # Kx2-L + b'\0\x001\x02\x10\x01\0\0H\x11', # misc (Ix2, KC2-A, uPD78F0730) + b'\0\x001\x02\x11\x01\0\0H\x11', # FC2 + b'\0\x001\x02\x12\x01\0\0H\x11', # Lx3 + b'\0\x002\x02\0\x01\0\0H\x11', # misc (uPD78F8077, Dx2, Kx2-C, uPD78F8039) + b'\0\x002\x02\x02\x01\0\0H\x11', # Fx2-L + b'\0\x002\x02\x10\x01\0\0H\x11', # Lx3-M } IDK_KNOWN_78K0R = { b'\x0b\0\0\x03 \x02\0\0H\x11', # KC3-L diff --git a/svd/svd.py b/svd/svd.py index 0225136..ae57421 100644 --- a/svd/svd.py +++ b/svd/svd.py @@ -2,6 +2,11 @@ from typing import * +class Diff(NamedTuple): + fullname: str + values: Tuple[Any,Any] + + SvdEndian = Literal["little", "big", "selectable", "other"] SvdSauAccess = Literal["n", "c", "s"] SvdProtection = Literal["s", "n", "p"] @@ -22,12 +27,46 @@ SvdReadAction = Literal["clear", "set", "modify", "modifyExternal"] SvdAccess = Literal["read-only", "write-only", "read-write", "writeOnce", "read-writeOnce"] +def diff_base(a, b, base, T, names): + for n in names: + av = a.__getattribute__(n) + bv = b.__getattribute__(n) + if av != bv: + yield Diff("%s.%s"%(base,n),(av,bv)) + +def diff_structmemb(a, b, base, T, name): + av = a.__getattribute__(name) + bv = b.__getattribute__(name) + if av is None and bv is None: pass + elif (av is None and bv is not None) or (av is not None and bv is None): + yield Diff("%s.%s"%(base,name),(av,bv)) + else: + yield from av.__diff__(bv, "%s.%s"%(base,name)) + +def diff_structseq(a, b, base, T, name): + av = a.__getattribute__(name) + bv = b.__getattribute__(name) + if av is None and bv is None: pass + elif (av is None and bv is not None) or (av is not None and bv is None): + yield Diff("%s.%s"%(base,name),(av,bv)) + elif len(av) != len(bv): + yield Diff("%s.%s#"%(base,name), (len(av), len(bv))) + else: + for i in range(len(av)): + yield from av[i].__diff__(bv[i], "%s.%s[%d]"%(base,name,i)) + + class SvdSauRegion(NamedTuple): - enabled: bool # attribute - name: str # attribute - base: int - limit: int - access: SvdSauAccess + enabled: bool = None # attribute + name: str = None # attribute + base: int = None + limit: int = None + access: SvdSauAccess = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdSauRegion, + ['enabled','name','base','limit','access']) + class SvdSauRegionsConfig(NamedTuple): @@ -35,168 +74,260 @@ class SvdSauRegionsConfig(NamedTuple): protectionWhenDisabled: SvdSauAccess # attribute regions: Sequence[SvdSauRegion] + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdSauRegionsConfig, + ['enabled','protectionWhenDisabled']) + yield from diff_structseq(self, other, base, SvdSauRegionsConfig, 'regions') + class SvdCpu(NamedTuple): name: str # explicitly not restricting to standard CMSIS names, because we'll be doing non-ARM stuff anyway - revision: Tuple[int, int] - endian: SvdEndian - mpuPresent: bool - fpuPresent: bool - fpuDP: bool - dspPresent: bool - icachePresent: bool - dcachePresent: bool - itcmPresent: bool - dtcmPresent: bool - vtorPresent: bool - nvicPrioBits: int - vendorSystickConfig: bool - deviceNumInterrupts: int - sauNumRegions: int - sauRegionsConfig: SvdSauRegionsConfig + revision: Tuple[int, int] = None + endian: SvdEndian = None + mpuPresent: bool = None + fpuPresent: bool = None + fpuDP: bool = None + dspPresent: bool = None + icachePresent: bool = None + dcachePresent: bool = None + itcmPresent: bool = None + dtcmPresent: bool = None + vtorPresent: bool = None + nvicPrioBits: int = None + vendorSystickConfig: bool = None + deviceNumInterrupts: int = None + sauNumRegions: int = None + sauRegionsConfig: SvdSauRegionsConfig = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdCpu, + ['name','revision','endian','mpuPresent','fpuPresent','fpuDP', + 'dspPresent','icachePresent','dcachePresent','itcmPresent', + 'dtcmPresent','vtorPresent','nvicPrioBits','vendorSystickConfig', + 'deviceNumInterrupts','sauNumRegions']) + yield from diff_structmemb(self, other, base, SvdCpu, 'sauRegionsConfig') class SvdRegisterProperties(NamedTuple): - size: int - access: SvdAccess - protection: SvdProtection - resetValue: int - resetMask: int + size: int = None + access: SvdAccess = None + protection: SvdProtection = None + resetValue: int = None + resetMask: int = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdRegisterProperties, + ['size','access','protection','resetValue','resetMask']) class SvdEnumeratedValue(NamedTuple): - name: str - description: str - value: int - isDefault: bool + name: str = None + description: str = None + value: int = None + isDefault: bool = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdEnumeratedValue, + ['name','description','value','isDefault']) + class SvdEnumeratedValues(NamedTuple): - derivedFrom: str # attribute - name: str - usage: SvdUsage - enumeratedValue: Sequence[SvdEnumeratedValue] + derivedFrom: str = None # attribute + name: str = None + usage: SvdUsage = None + enumeratedValue: Sequence[SvdEnumeratedValue] = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdEnumeratedValues, + ['derivedFrom','name','usage']) + yield from diff_structseq(self, other, base, SvdEnumeratedValues, 'enumeratedValue') class SvdDimArrayIndex(NamedTuple): - headerEnumName: str - enumeratedValue: SvdEnumeratedValue + headerEnumName: str = None + enumeratedValue: SvdEnumeratedValue = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdDimArrayIndex, + ['headerEnumName','enumeratedValue']) class SvdDimElement(NamedTuple): - dim: int - dimIncrement: int - dimIndex: str - dimName: str - dimArrayIndex: SvdDimArrayIndex + dim: int = None + dimIncrement: int = None + dimIndex: str = None + dimName: str = None + dimArrayIndex: SvdDimArrayIndex = None + headerEnumName: str = None + enumeratedValue: SvdEnumeratedValue = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdDimElement, + ['dim','dimIncrement','dimIndex','dimName','headerEnumName']) + yield from diff_structmemb(self, other, base, SvdDimElement, 'dimArrayIndex') + yield from diff_structmemb(self, other, base, SvdDimElement, 'enumeratedValue') + class SvdAddressBlock(NamedTuple): - offset: int - size: int - usage: SvdAddressUsage - protection: SvdProtection + offset: int = None + size: int = None + usage: SvdAddressUsage = None + protection: SvdProtection = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdAddressBlock, + ['offset','size','usage','protection']) class SvdInterrupt(NamedTuple): - name: str - description: str - value: int + name: str = None + description: str = None + value: int = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdInterrupt, + ['name','description','value']) class SvdCluster(NamedTuple): - derivedFrom: str # attribute - dimElement: SvdDimElement - name: str - description: str - alternateCluster: str - headerStructName: str - addressOffset: int - registerProperties: SvdRegisterProperties - register: Sequence[Any] - cluster: Sequence[Any] + derivedFrom: str = None # attribute + dimElement: SvdDimElement = None + name: str = None + description: str = None + alternateCluster: str = None + headerStructName: str = None + addressOffset: int = None + registerProperties: SvdRegisterProperties = None + register: Sequence[Any] = None + cluster: Sequence[Any] = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdCluster, + ['name','description','value']) + yield from diff_structmemb(self, other, base, SvdCluster, 'registerProperties') + yield from diff_structseq(self, other, base, SvdCluster, 'register') + yield from diff_structseq(self, other, base, SvdCluster, 'cluster') class SvdWriteConstraintRange(NamedTuple): - minimum: int - maximum: int + minimum: int = None + maximum: int = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdWriteConstraintRange, + ['minimum','maximum']) class SvdWriteConstraint(NamedTuple): - writeAsRead: bool - useEnumeratedValues: bool - range: SvdWriteConstraintRange + writeAsRead: bool = None + useEnumeratedValues: bool = None + range: SvdWriteConstraintRange = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdWriteConstraint, + ['writeAsRead','useEnumeratedValues']) + yield from diff_structmemb(self, other, base, SvdWriteConstraint, 'range') class SvdField(NamedTuple): - derivedFrom: str # attribute - dimElement: SvdDimElement - name: str - description: str - bitOffset: int - bitWidth: int - lsb: int - msb: int - bitRange: str - access: SvdAccess - modifiedWriteValues: SvdModifiedWriteValues - writeConstraint: SvdWriteConstraint - readAction: SvdReadAction - enumeratedValues: SvdEnumeratedValues + derivedFrom: str = None # attribute + dimElement: SvdDimElement = None + name: str = None + description: str = None + bitOffset: int = None + bitWidth: int = None + lsb: int = None + msb: int = None + bitRange: str = None + access: SvdAccess = None + modifiedWriteValues: SvdModifiedWriteValues = None + writeConstraint: SvdWriteConstraint = None + readAction: SvdReadAction = None + enumeratedValues: SvdEnumeratedValues = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdField, + ['derivedFrom','name','description','bitOffset','bitWidth','lsb', + 'msb','bitRange','access','modifiedWriteValues','readAction']) + yield from diff_structmemb(self, other, base, SvdField, 'dimElement') + yield from diff_structmemb(self, other, base, SvdField, 'writeConstraint') + yield from diff_structmemb(self, other, base, SvdField, 'enumeratedValues') class SvdRegister(NamedTuple): - derivedFrom: str # attribute - dimElement: SvdDimElement - name: str - displayName: str - description: str - alternateGroup: str - alternateRegister: str - addressOffset: int - registerProperties: SvdRegisterProperties - dataType: SvdDataType - modifiedWriteValues: SvdModifiedWriteValues - writeConstraint: SvdWriteConstraint - readAction: SvdReadAction - fields: Sequence[SvdField] + derivedFrom: str = None # attribute + dimElement: SvdDimElement = None + name: str = None + displayName: str = None + description: str = None + alternateGroup: str = None + alternateRegister: str = None + addressOffset: int = None + registerProperties: SvdRegisterProperties = None + dataType: SvdDataType = None + modifiedWriteValues: SvdModifiedWriteValues = None + writeConstraint: SvdWriteConstraint = None + readAction: SvdReadAction = None + fields: Sequence[SvdField] = None # ignoring for now because this SVD is VERY broken #enumeratedValues: SvdEnumeratedValues # HACK: SiFive e310x, Kendryte k210 + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdRegister, + ['derivedFrom','name','displayName','description','alternateGroup', + 'alternateRegister','addressOffset','dataType','modifiedWriteValues', + 'readAction']) + yield from diff_structmemb(self, other, base, SvdRegister, 'dimElement') + yield from diff_structmemb(self, other, base, SvdRegister, 'registerProperties') + yield from diff_structmemb(self, other, base, SvdRegister, 'writeConstraint') + yield from diff_structseq(self, other, base, SvdRegister, 'fields') + class SvdPeripheral(NamedTuple): - derivedFrom: str # attribute - name: str - version: str - description: str - alternatePeripheral: str - groupName: str - prependToName: str - appendToName: str - headerStructName: str - disableCondition: str - baseAddress: int - registerProperties: SvdRegisterProperties - addressBlock: Sequence[SvdAddressBlock] - interrupt: Sequence[SvdInterrupt] - registers: Sequence[Union[SvdRegister, SvdCluster]] + derivedFrom: str = None # attribute + name: str = None + version: str = None + description: str = None + alternatePeripheral: str = None + groupName: str = None + prependToName: str = None + appendToName: str = None + headerStructName: str = None + disableCondition: str = None + baseAddress: int = None + registerProperties: SvdRegisterProperties = None + addressBlock: Sequence[SvdAddressBlock] = None + interrupt: Sequence[SvdInterrupt] = None + registers: Sequence[Union[SvdRegister, SvdCluster]] = None + + def __diff__(self, other, base): + yield from diff_base(self, other, base, SvdPeripheral, + ['derivedFrom','name','version','description','alternatePeripheral', + 'groupName','prependToName','appendToName','headerStructName', + 'disableCondition','baseAddress']) + yield from diff_structmemb(self, other, base, SvdPeripheral, 'registerProperties') + yield from diff_structseq(self, other, base, SvdPeripheral, 'addressBlock') + yield from diff_structseq(self, other, base, SvdPeripheral, 'interrupt') + yield from diff_structseq(self, other, base, SvdPeripheral, 'registers') class SvdDevice(NamedTuple): vendor: str vendorID: str name: str - series: str - version: str - description: str - licenseText: str - cpu: SvdCpu - headerSystemFilename: str - headerDefinitionsPrefix: str - addressUnitBits: int - width: int - registerProperties: SvdRegisterProperties - peripherals: Sequence[SvdPeripheral] - vendorExtensions: Any + series: str = None + version: str = None + description: str = None + licenseText: str = None + cpu: SvdCpu = None + headerSystemFilename: str = None + headerDefinitionsPrefix: str = None + addressUnitBits: int = None + width: int = None + registerProperties: SvdRegisterProperties = None + peripherals: Sequence[SvdPeripheral] = None + vendorExtensions: Any = None def __eq__(self, other): return self.vendor == other.vendor and self.vendorID == other.vendorID \ @@ -208,6 +339,16 @@ class SvdDevice(NamedTuple): self.addressUnitBits == other.addressUnitBits and self.width == other.width \ and self.registerProperties == other.registerProperties and \ self.peripherals == other.peripherals + # ignore vendorExtensions + + def __diff__(self, other, base='device'): + yield from diff_base(self, other, base, SvdDevice, + ['vendor','vendorID','name','series','version','description', + 'licenseText','headerSystemFilename','headerDefinitionsPrefix', + 'addressUnitBits','width']) + yield from diff_structmemb(self, other, base, SvdDevice, 'cpu') + yield from diff_structmemb(self, other, base, SvdDevice, 'registerProperties') + yield from diff_structseq(self, other, base, SvdDevice, 'peripherals') # TODO: functions for expanding/flattening registerProperties, dimElements and derivedFrom? diff --git a/svd/svdparse.py b/svd/svdparse.py index dd8bda3..b466401 100644 --- a/svd/svdparse.py +++ b/svd/svdparse.py @@ -138,6 +138,14 @@ def parse_generic(xd, T: type, tag: str, return T(**d) +def parse_list_inner(f, l): + if l is None or len(l) == 0: return None + return [f(x) for x in l] + +def parse_list(f): + return (lambda l: parse_list_inner(f, l)) + + def parse_sauRegion(xd): return parse_generic(xd, SvdSauRegion, 'region') def parse_addressBlock(xd): return parse_generic(xd, SvdAddressBlock, 'addressBlock') def parse_interrupt(xd): return parse_generic(xd, SvdInterrupt, 'interrupt') @@ -173,7 +181,7 @@ def parse_field(xd): return parse_generic(xd, SvdField, 'field', False, True, Tr def parse_register(xd) -> SvdRegister: return parse_generic(xd, SvdRegister, 'register', True, True, True, { 'writeConstraint': parse_writeConstraint, - 'fields': (lambda ch: [parse_field(xch) for xch in ch]) + 'fields': parse_list(parse_field), #(lambda ch: [parse_field(xch) for xch in ch]) # FIXME }) @@ -186,12 +194,12 @@ def parse_registers(xd) -> Sequence[Union[SvdCluster, SvdRegister]]: rr.append(parse_register(ch)) else: assert False, ("expected cluster or register, got %s"%ch) - return rr + return rr if len(rr) > 0 else None def parse_peripheral(xd) -> SvdPeripheral: return parse_generic(xd, SvdPeripheral, 'peripheral', True, True, False, { - 'registers': parse_registers, # FIXME + 'registers': parse_registers, # FIXME # UUUH what was to be fixed again? }, { 'interrupt': parse_interrupt, 'addressBlock': parse_addressBlock @@ -201,7 +209,7 @@ def parse_peripheral(xd) -> SvdPeripheral: def parse_device(xd) -> SvdDevice: return parse_generic(xd, SvdDevice, 'device', True, 2, False, { 'cpu': parse_cpu, - 'peripherals': (lambda ch: [parse_peripheral(xch) for xch in ch]), + 'peripherals': parse_list(parse_peripheral), #(lambda ch: [parse_peripheral(xch) for xch in ch]), # FIXME 'vendorExtensions': (lambda ch: ch) })