mmiogrok/svd/svdgen.py

97 lines
3.0 KiB
Python

import typing, collections.abc
from svd import *
from typing import get_type_hints
# FIXME:
# * peripheral registers not emitting
def ser_one(v) -> str:
assert v is not None
if isinstance(v, bool): return "true" if v else "false"
elif isinstance(v, int): return hex(v)
elif isinstance(v, str): return v
elif type(v) == tuple:
return "r%dp%d" % (v[0], v[1])
else: return None
type2attr = {
SvdSauRegion: {'enabled','name'},
SvdSauRegionsConfig: {'enabled','protectionWhenDisabled'},
SvdEnumeratedValues: {'derivedFrom'},
SvdCluster: {'derivedFrom'},
SvdField: {'derivedFrom'},
SvdRegister: {'derivedFrom'},
SvdPeripheral: {'derivedFrom'},
}
type2tag = {
SvdSauRegion: 'region',
SvdSauRegionsConfig: 'sauRegionsConfig',
SvdCpu: 'cpu',
SvdRegisterProperties: 'registerProperties',
SvdEnumeratedValue: 'enumeratedValue',
SvdEnumeratedValues: 'enumeratedValues',
SvdDimArrayIndex: 'dimArrayIndex',
SvdDimElement: 'dimElement',
SvdAddressBlock: 'addressBlock',
SvdInterrupt: 'interrupt',
SvdCluster: 'cluster',
SvdWriteConstraintRange: 'range',
SvdWriteConstraint: 'writeConstraint',
SvdField: 'field',
SvdRegister: 'register',
SvdPeripheral: 'peripheral',
SvdDevice: 'device',
}
def gen_generic(f, svdelem, T, tag, attrs=(), extraattr="", no_outer=False):
atdict={}
childdict={}
d = dict((n, svdelem.__getattribute__(n)) for n in T._fields)
for k, v in d.items():
if v is None: continue
if k in attrs:
atdict[k] = v
else:
childdict[k] = v
atstr = ' '.join('%s="%s"' % (k, ser_one(v)) for k, v in atdict.items())
if not no_outer: f.write("<%s%s%s%s>\n" % (tag, (' ' if len(atstr)+len(extraattr)>0 else ''), atstr, extraattr))
types = get_type_hints(T)
for k, v in childdict.items():
if v is None: continue
typ = types[k]
x = ser_one(v)
if x is None: # TODO: optimize
if '__origin__' in typ.__dict__ and typ.__origin__ == collections.abc.Sequence:
if len(v) > 0:
f.write("<%s>\n" % k)
ttt = typ.__args__[0]
isunion = '__origin__' in ttt.__dict__ and ttt.__origin__ == typing.Union
for x in v:
if isunion: ttt = type(x)
gen_generic(f, x, ttt, type2tag[ttt], type2attr.get(ttt, ()))
f.write("</%s>\n" % k)
else:
noouter = typ in {SvdDimElement, SvdRegisterProperties}
gen_generic(f, v, typ, k, type2attr.get(typ, ()), no_outer=noouter)
else:
f.write("<%s>%s</%s>\n"%(k, x, k))
if not no_outer: f.write("</%s>\n" % tag)
def generate(f, dev: SvdDevice):
f.write("""<?xml version="1.0" encoding="utf-8"?>\n""")
gen_generic(f, dev, SvdDevice, 'device',
extraattr=""" schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" """)