svd diffing

This commit is contained in:
Triss 2022-06-01 16:48:02 +02:00
parent bab3f7141f
commit 748b88e71e
3 changed files with 281 additions and 132 deletions

View File

@ -197,16 +197,16 @@ class Dvf(NamedTuple):
MCU_RL78x2y = 0x30 MCU_RL78x2y = 0x30
IDK_KNOWN_78K0 = { IDK_KNOWN_78K0 = {
b'\0\01\x02!\x02\0\0H\x11', # Kx2 b'\0\x001\x02!\x02\0\0H\x11', # Kx2
b'\0\01\x02\0\x01\0\0H\x11', # Kx2-A, uPD78F8039 b'\0\x001\x02\0\x01\0\0H\x11', # Kx2-A, uPD78F8039
b'\0\01\x02\x01\x01\0\0H\x11', # Fx2 b'\0\x001\x02\x01\x01\0\0H\x11', # Fx2
b'\0\01\x02\x01\x02\0\0H\x11', # Kx2-L b'\0\x001\x02\x01\x02\0\0H\x11', # Kx2-L
b'\0\01\x02\x10\x01\0\0H\x11', # misc (Ix2, KC2-A, uPD78F0730) b'\0\x001\x02\x10\x01\0\0H\x11', # misc (Ix2, KC2-A, uPD78F0730)
b'\0\01\x02\x11\x01\0\0H\x11', # FC2 b'\0\x001\x02\x11\x01\0\0H\x11', # FC2
b'\0\01\x02\x12\x01\0\0H\x11', # Lx3 b'\0\x001\x02\x12\x01\0\0H\x11', # Lx3
b'\0\02\x02\0\x01\0\0H\x11', # misc (uPD78F8077, Dx2, Kx2-C, uPD78F8039) b'\0\x002\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\x002\x02\x02\x01\0\0H\x11', # Fx2-L
b'\0\02\x02\x10\x01\0\0H\x11', # Lx3-M b'\0\x002\x02\x10\x01\0\0H\x11', # Lx3-M
} }
IDK_KNOWN_78K0R = { IDK_KNOWN_78K0R = {
b'\x0b\0\0\x03 \x02\0\0H\x11', # KC3-L b'\x0b\0\0\x03 \x02\0\0H\x11', # KC3-L

View File

@ -2,6 +2,11 @@
from typing import * from typing import *
class Diff(NamedTuple):
fullname: str
values: Tuple[Any,Any]
SvdEndian = Literal["little", "big", "selectable", "other"] SvdEndian = Literal["little", "big", "selectable", "other"]
SvdSauAccess = Literal["n", "c", "s"] SvdSauAccess = Literal["n", "c", "s"]
SvdProtection = Literal["s", "n", "p"] 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"] 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): class SvdSauRegion(NamedTuple):
enabled: bool # attribute enabled: bool = None # attribute
name: str # attribute name: str = None # attribute
base: int base: int = None
limit: int limit: int = None
access: SvdSauAccess access: SvdSauAccess = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdSauRegion,
['enabled','name','base','limit','access'])
class SvdSauRegionsConfig(NamedTuple): class SvdSauRegionsConfig(NamedTuple):
@ -35,168 +74,260 @@ class SvdSauRegionsConfig(NamedTuple):
protectionWhenDisabled: SvdSauAccess # attribute protectionWhenDisabled: SvdSauAccess # attribute
regions: Sequence[SvdSauRegion] 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): class SvdCpu(NamedTuple):
name: str # explicitly not restricting to standard CMSIS names, because we'll be doing non-ARM stuff anyway name: str # explicitly not restricting to standard CMSIS names, because we'll be doing non-ARM stuff anyway
revision: Tuple[int, int] revision: Tuple[int, int] = None
endian: SvdEndian endian: SvdEndian = None
mpuPresent: bool mpuPresent: bool = None
fpuPresent: bool fpuPresent: bool = None
fpuDP: bool fpuDP: bool = None
dspPresent: bool dspPresent: bool = None
icachePresent: bool icachePresent: bool = None
dcachePresent: bool dcachePresent: bool = None
itcmPresent: bool itcmPresent: bool = None
dtcmPresent: bool dtcmPresent: bool = None
vtorPresent: bool vtorPresent: bool = None
nvicPrioBits: int nvicPrioBits: int = None
vendorSystickConfig: bool vendorSystickConfig: bool = None
deviceNumInterrupts: int deviceNumInterrupts: int = None
sauNumRegions: int sauNumRegions: int = None
sauRegionsConfig: SvdSauRegionsConfig 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): class SvdRegisterProperties(NamedTuple):
size: int size: int = None
access: SvdAccess access: SvdAccess = None
protection: SvdProtection protection: SvdProtection = None
resetValue: int resetValue: int = None
resetMask: int resetMask: int = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdRegisterProperties,
['size','access','protection','resetValue','resetMask'])
class SvdEnumeratedValue(NamedTuple): class SvdEnumeratedValue(NamedTuple):
name: str name: str = None
description: str description: str = None
value: int value: int = None
isDefault: bool isDefault: bool = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdEnumeratedValue,
['name','description','value','isDefault'])
class SvdEnumeratedValues(NamedTuple): class SvdEnumeratedValues(NamedTuple):
derivedFrom: str # attribute derivedFrom: str = None # attribute
name: str name: str = None
usage: SvdUsage usage: SvdUsage = None
enumeratedValue: Sequence[SvdEnumeratedValue] 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): class SvdDimArrayIndex(NamedTuple):
headerEnumName: str headerEnumName: str = None
enumeratedValue: SvdEnumeratedValue enumeratedValue: SvdEnumeratedValue = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdDimArrayIndex,
['headerEnumName','enumeratedValue'])
class SvdDimElement(NamedTuple): class SvdDimElement(NamedTuple):
dim: int dim: int = None
dimIncrement: int dimIncrement: int = None
dimIndex: str dimIndex: str = None
dimName: str dimName: str = None
dimArrayIndex: SvdDimArrayIndex 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): class SvdAddressBlock(NamedTuple):
offset: int offset: int = None
size: int size: int = None
usage: SvdAddressUsage usage: SvdAddressUsage = None
protection: SvdProtection protection: SvdProtection = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdAddressBlock,
['offset','size','usage','protection'])
class SvdInterrupt(NamedTuple): class SvdInterrupt(NamedTuple):
name: str name: str = None
description: str description: str = None
value: int value: int = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdInterrupt,
['name','description','value'])
class SvdCluster(NamedTuple): class SvdCluster(NamedTuple):
derivedFrom: str # attribute derivedFrom: str = None # attribute
dimElement: SvdDimElement dimElement: SvdDimElement = None
name: str name: str = None
description: str description: str = None
alternateCluster: str alternateCluster: str = None
headerStructName: str headerStructName: str = None
addressOffset: int addressOffset: int = None
registerProperties: SvdRegisterProperties registerProperties: SvdRegisterProperties = None
register: Sequence[Any] register: Sequence[Any] = None
cluster: Sequence[Any] 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): class SvdWriteConstraintRange(NamedTuple):
minimum: int minimum: int = None
maximum: int maximum: int = None
def __diff__(self, other, base):
yield from diff_base(self, other, base, SvdWriteConstraintRange,
['minimum','maximum'])
class SvdWriteConstraint(NamedTuple): class SvdWriteConstraint(NamedTuple):
writeAsRead: bool writeAsRead: bool = None
useEnumeratedValues: bool useEnumeratedValues: bool = None
range: SvdWriteConstraintRange 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): class SvdField(NamedTuple):
derivedFrom: str # attribute derivedFrom: str = None # attribute
dimElement: SvdDimElement dimElement: SvdDimElement = None
name: str name: str = None
description: str description: str = None
bitOffset: int bitOffset: int = None
bitWidth: int bitWidth: int = None
lsb: int lsb: int = None
msb: int msb: int = None
bitRange: str bitRange: str = None
access: SvdAccess access: SvdAccess = None
modifiedWriteValues: SvdModifiedWriteValues modifiedWriteValues: SvdModifiedWriteValues = None
writeConstraint: SvdWriteConstraint writeConstraint: SvdWriteConstraint = None
readAction: SvdReadAction readAction: SvdReadAction = None
enumeratedValues: SvdEnumeratedValues 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): class SvdRegister(NamedTuple):
derivedFrom: str # attribute derivedFrom: str = None # attribute
dimElement: SvdDimElement dimElement: SvdDimElement = None
name: str name: str = None
displayName: str displayName: str = None
description: str description: str = None
alternateGroup: str alternateGroup: str = None
alternateRegister: str alternateRegister: str = None
addressOffset: int addressOffset: int = None
registerProperties: SvdRegisterProperties registerProperties: SvdRegisterProperties = None
dataType: SvdDataType dataType: SvdDataType = None
modifiedWriteValues: SvdModifiedWriteValues modifiedWriteValues: SvdModifiedWriteValues = None
writeConstraint: SvdWriteConstraint writeConstraint: SvdWriteConstraint = None
readAction: SvdReadAction readAction: SvdReadAction = None
fields: Sequence[SvdField] fields: Sequence[SvdField] = None
# ignoring for now because this SVD is VERY broken # ignoring for now because this SVD is VERY broken
#enumeratedValues: SvdEnumeratedValues # HACK: SiFive e310x, Kendryte k210 #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): class SvdPeripheral(NamedTuple):
derivedFrom: str # attribute derivedFrom: str = None # attribute
name: str name: str = None
version: str version: str = None
description: str description: str = None
alternatePeripheral: str alternatePeripheral: str = None
groupName: str groupName: str = None
prependToName: str prependToName: str = None
appendToName: str appendToName: str = None
headerStructName: str headerStructName: str = None
disableCondition: str disableCondition: str = None
baseAddress: int baseAddress: int = None
registerProperties: SvdRegisterProperties registerProperties: SvdRegisterProperties = None
addressBlock: Sequence[SvdAddressBlock] addressBlock: Sequence[SvdAddressBlock] = None
interrupt: Sequence[SvdInterrupt] interrupt: Sequence[SvdInterrupt] = None
registers: Sequence[Union[SvdRegister, SvdCluster]] 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): class SvdDevice(NamedTuple):
vendor: str vendor: str
vendorID: str vendorID: str
name: str name: str
series: str series: str = None
version: str version: str = None
description: str description: str = None
licenseText: str licenseText: str = None
cpu: SvdCpu cpu: SvdCpu = None
headerSystemFilename: str headerSystemFilename: str = None
headerDefinitionsPrefix: str headerDefinitionsPrefix: str = None
addressUnitBits: int addressUnitBits: int = None
width: int width: int = None
registerProperties: SvdRegisterProperties registerProperties: SvdRegisterProperties = None
peripherals: Sequence[SvdPeripheral] peripherals: Sequence[SvdPeripheral] = None
vendorExtensions: Any vendorExtensions: Any = None
def __eq__(self, other): def __eq__(self, other):
return self.vendor == other.vendor and self.vendorID == other.vendorID \ 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 \ self.addressUnitBits == other.addressUnitBits and self.width == other.width \
and self.registerProperties == other.registerProperties and \ and self.registerProperties == other.registerProperties and \
self.peripherals == other.peripherals 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? # TODO: functions for expanding/flattening registerProperties, dimElements and derivedFrom?

View File

@ -138,6 +138,14 @@ def parse_generic(xd, T: type, tag: str,
return T(**d) 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_sauRegion(xd): return parse_generic(xd, SvdSauRegion, 'region')
def parse_addressBlock(xd): return parse_generic(xd, SvdAddressBlock, 'addressBlock') def parse_addressBlock(xd): return parse_generic(xd, SvdAddressBlock, 'addressBlock')
def parse_interrupt(xd): return parse_generic(xd, SvdInterrupt, 'interrupt') 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: def parse_register(xd) -> SvdRegister:
return parse_generic(xd, SvdRegister, 'register', True, True, True, { return parse_generic(xd, SvdRegister, 'register', True, True, True, {
'writeConstraint': parse_writeConstraint, '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)) rr.append(parse_register(ch))
else: else:
assert False, ("expected cluster or register, got %s"%ch) assert False, ("expected cluster or register, got %s"%ch)
return rr return rr if len(rr) > 0 else None
def parse_peripheral(xd) -> SvdPeripheral: def parse_peripheral(xd) -> SvdPeripheral:
return parse_generic(xd, SvdPeripheral, 'peripheral', True, True, False, { 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, 'interrupt': parse_interrupt,
'addressBlock': parse_addressBlock 'addressBlock': parse_addressBlock
@ -201,7 +209,7 @@ def parse_peripheral(xd) -> SvdPeripheral:
def parse_device(xd) -> SvdDevice: def parse_device(xd) -> SvdDevice:
return parse_generic(xd, SvdDevice, 'device', True, 2, False, { return parse_generic(xd, SvdDevice, 'device', True, 2, False, {
'cpu': parse_cpu, '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) 'vendorExtensions': (lambda ch: ch)
}) })