import xml, xml.etree import xml.etree.ElementTree as ET import typing, collections.abc from svd import * from typing import get_type_hints 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.replace('&', "&").replace('<', "<").replace('>', ">") 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', } flattenchildren = { SvdEnumeratedValues: {'enumeratedValue'}, SvdCluster: {'cluster','register'}, SvdDimArrayIndex: {'enumeratedValue'}, SvdPeripheral: {'interrupt','addressBlock'}, } def gen_generic(f, svdelem, T: type, tag: str, attrs=(), extraattr="", no_outer=False, rec=[]): rec=[*rec, tag] #print(rec, T, type(svdelem)) 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 #print('k', k, "typ",typ) if typ == typing.Any and k == 'vendorExtensions': if type(v) == ET.Element: #print("v",v,type(v)) xstr = ET.tostring(v, method='xml')#, encoding='utf8') xstr = xstr.decode() #print("xstr",xstr) f.write(xstr) else: # uuuuuh idk fuck f.write(repr(v)) f.write('\n') elif typ == list or ('__origin__' in typ.__dict__ and typ.__origin__ in {collections.abc.Sequence,list}): if len(v) > 0: flatten = k in flattenchildren.get(T, ()) if not flatten: f.write("<%s>\n" % k) ttt = typ.__args__[0] isdyn = ttt == typing.Any or ('__origin__' in ttt.__dict__ and ttt.__origin__ == typing.Union) for x in v: if isdyn: ttt = type(x) #print("ttt",ttt) gen_generic(f, x, ttt, type2tag[ttt], type2attr.get(ttt, ()), rec=[*rec, k]) if not flatten: f.write("\n" % k) else: noouter = typ in {SvdDimElement, SvdRegisterProperties} gen_generic(f, v, typ, k, type2attr.get(typ, ()), no_outer=noouter, rec=[*rec, k]) else: f.write("<%s>%s\n"%(k, x, k)) if not no_outer: f.write("\n" % tag) def generate(f, dev: SvdDevice): f.write("""\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" """)