tools/gen-device-svd: rewrite with ElementTree

xml.etree.ElementTree is much easier to work with. This also fixes a few
small bugs in the parser. And as an added bonus, device generation got a
lot faster: apprently etree is a lot faster than minidom.
Этот коммит содержится в:
Ayke van Laethem 2018-09-30 12:48:03 +02:00
родитель ee5d562050
коммит e77a5af5d2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED

Просмотреть файл

@ -2,7 +2,7 @@
import sys
import os
from xml.dom import minidom
from xml.etree import ElementTree
from glob import glob
from collections import OrderedDict
import re
@ -13,11 +13,7 @@ class Device:
pass
def getText(element):
strings = []
for node in element.childNodes:
if node.nodeType == node.TEXT_NODE:
strings.append(node.data)
return ''.join(strings)
return ''.join(element.itertext())
def formatText(text):
text = re.sub('[ \t\n]+', ' ', text) # Collapse whitespace (like in HTML)
@ -28,11 +24,11 @@ def formatText(text):
def readSVD(path, sourceURL):
# Read ARM SVD files.
device = Device()
xml = minidom.parse(path)
root = xml.getElementsByTagName('device')[0]
deviceName = getText(root.getElementsByTagName('name')[0])
deviceDescription = getText(root.getElementsByTagName('description')[0]).strip()
licenseTexts = root.getElementsByTagName('licenseText')
xml = ElementTree.parse(path)
root = xml.getroot()
deviceName = getText(root.find('name'))
deviceDescription = getText(root.find('description')).strip()
licenseTexts = root.findall('licenseText')
if len(licenseTexts) == 0:
licenseText = None
elif len(licenseTexts) == 1:
@ -46,21 +42,21 @@ def readSVD(path, sourceURL):
interrupts = OrderedDict()
for periphEl in root.getElementsByTagName('peripherals')[0].getElementsByTagName('peripheral'):
name = getText(periphEl.getElementsByTagName('name')[0])
descriptionTags = periphEl.getElementsByTagName('description')
for periphEl in root.findall('./peripherals/peripheral'):
name = getText(periphEl.find('name'))
descriptionTags = periphEl.findall('description')
description = ''
if descriptionTags:
description = formatText(getText(descriptionTags[0]))
baseAddress = int(getText(periphEl.getElementsByTagName('baseAddress')[0]), 0)
groupNameTags = periphEl.getElementsByTagName('groupName')
baseAddress = int(getText(periphEl.find('baseAddress')), 0)
groupNameTags = periphEl.findall('groupName')
groupName = None
if groupNameTags:
groupName = getText(groupNameTags[0])
if periphEl.hasAttribute('derivedFrom') or groupName in groups:
if periphEl.hasAttribute('derivedFrom'):
derivedFromName = periphEl.getAttribute('derivedFrom')
if periphEl.get('derivedFrom') or groupName in groups:
if periphEl.get('derivedFrom'):
derivedFromName = periphEl.get('derivedFrom')
derivedFrom = peripheralDict[derivedFromName]
else:
derivedFrom = groups[groupName]
@ -87,9 +83,9 @@ def readSVD(path, sourceURL):
if groupName and groupName not in groups:
groups[groupName] = peripheral
for interrupt in periphEl.getElementsByTagName('interrupt'):
intrName = getText(interrupt.getElementsByTagName('name')[0])
intrIndex = int(getText(interrupt.getElementsByTagName('value')[0]))
for interrupt in periphEl.findall('interrupt'):
intrName = getText(interrupt.find('name'))
intrIndex = int(getText(interrupt.find('value')))
if intrName in interrupts:
if interrupts[intrName]['index'] != intrIndex:
raise ValueError('interrupt with the same name has different indexes: ' + intrName)
@ -101,19 +97,19 @@ def readSVD(path, sourceURL):
'description': description,
}
regsEls = periphEl.getElementsByTagName('registers')
regsEls = periphEl.findall('registers')
if regsEls:
for el in regsEls[0].childNodes:
if el.nodeName == 'register':
peripheral['registers'].append(parseSVDRegister(groupName or name, el, baseAddress))
elif el.nodeName == 'cluster':
if el.getElementsByTagName('dim'):
continue # TODO
clusterPrefix = getText(el.getElementsByTagName('name')[0]) + '_'
clusterOffset = int(getText(el.getElementsByTagName('addressOffset')[0]), 0)
for regEl in el.childNodes:
if regEl.nodeName == 'register':
peripheral['registers'].append(parseSVDRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix))
if len(regsEls) != 1:
raise ValueError('expected just one <registers> in a <peripheral>')
for register in regsEls[0].findall('register'):
peripheral['registers'].append(parseRegister(groupName or name, register, baseAddress))
for cluster in regsEls[0].findall('cluster'):
if cluster.find('dim') is not None:
continue # TODO
clusterPrefix = getText(cluster.find('name')) + '_'
clusterOffset = int(getText(cluster.find('addressOffset')), 0)
for regEl in cluster.findall('register'):
peripheral['registers'].append(parseRegister(groupName or name, regEl, baseAddress + clusterOffset, clusterPrefix))
else:
continue
@ -133,38 +129,36 @@ def readSVD(path, sourceURL):
return device
def parseSVDRegister(groupName, regEl, baseAddress, namePrefix=''):
regName = getText(regEl.getElementsByTagName('name')[0])
regDescription = getText(regEl.getElementsByTagName('description')[0])
offsetEls = regEl.getElementsByTagName('offset')
def parseRegister(groupName, regEl, baseAddress, namePrefix=''):
regName = getText(regEl.find('name'))
regDescription = getText(regEl.find('description'))
offsetEls = regEl.findall('offset')
if not offsetEls:
offsetEls = regEl.getElementsByTagName('addressOffset')
offsetEls = regEl.findall('addressOffset')
address = baseAddress + int(getText(offsetEls[0]), 0)
dimEls = regEl.getElementsByTagName('dim')
dimEls = regEl.findall('dim')
array = None
if dimEls:
array = int(getText(dimEls[0]), 0)
regName = regName.replace('[%s]', '')
fields = []
fieldsEls = regEl.getElementsByTagName('fields')
fieldsEls = regEl.findall('fields')
if fieldsEls:
for fieldEl in fieldsEls[0].childNodes:
if fieldEl.nodeName != 'field':
continue
fieldName = getText(fieldEl.getElementsByTagName('name')[0])
descrEls = fieldEl.getElementsByTagName('description')
lsbTags = fieldEl.getElementsByTagName('lsb')
for fieldEl in fieldsEls[0].findall('field'):
fieldName = getText(fieldEl.find('name'))
descrEls = fieldEl.findall('description')
lsbTags = fieldEl.findall('lsb')
if len(lsbTags) == 1:
lsb = int(getText(lsbTags[0]))
else:
lsb = int(getText(fieldEl.getElementsByTagName('bitOffset')[0]))
msbTags = fieldEl.getElementsByTagName('msb')
lsb = int(getText(fieldEl.find('bitOffset')))
msbTags = fieldEl.findall('msb')
if len(msbTags) == 1:
msb = int(getText(msbTags[0]))
else:
msb = int(getText(fieldEl.getElementsByTagName('bitWidth')[0])) + lsb - 1
msb = int(getText(fieldEl.find('bitWidth'))) + lsb - 1
fields.append({
'name': '{}_{}{}_{}_Pos'.format(groupName, namePrefix, regName, fieldName),
'description': 'Position of %s field.' % fieldName,
@ -181,10 +175,10 @@ def parseSVDRegister(groupName, regEl, baseAddress, namePrefix=''):
'description': 'Bit %s.' % fieldName,
'value': 1 << lsb,
})
for enumEl in fieldEl.getElementsByTagName('enumeratedValue'):
enumName = getText(enumEl.getElementsByTagName('name')[0])
enumDescription = getText(enumEl.getElementsByTagName('description')[0])
enumValue = int(getText(enumEl.getElementsByTagName('value')[0]), 0)
for enumEl in fieldEl.findall('enumeratedValues/enumeratedValue'):
enumName = getText(enumEl.find('name'))
enumDescription = getText(enumEl.find('description'))
enumValue = int(getText(enumEl.find('value')), 0)
fields.append({
'name': '{}_{}{}_{}_{}'.format(groupName, namePrefix, regName, fieldName, enumName),
'description': enumDescription,
@ -265,7 +259,7 @@ const (
out.write('\t{name} {regType}\n'.format(**register, regType=regType))
# next address
if register['array'] is not None and 1:
if register['array'] is not None:
address = register['address'] + 4 * register['array']
else:
address = register['address'] + 4