def process_device(device, ppath, quiet): # Load the SVD and process all modifications from the yaml # (but don't bother actually applying the enums/ranges). svdpath = svdpatch.abspath(device["_path"], device["_svd"]) if not quiet: print("Loading SVD {} for {}".format(svdpath, device["_path"])) tree = ET.parse(svdpath) if not quiet: print("Processing existing device peripherals") already_included = svdpatch.yaml_includes(device) svdpatch.process_device(tree, device, False) # Now go through every YAML file we can find and see if they could be # matched against the device if not quiet: print("Matching against remaining peripherals") matches = [] if os.path.isfile(ppath): yamlpath = os.path.realpath(ppath) if yamlpath not in already_included: if process_yamlfile(tree, ppath, quiet): matches.append(ppath) else: for root, dirnames, filenames in os.walk(ppath): for filename in fnmatch.filter(filenames, "*.yaml"): yamlpath = os.path.realpath(os.path.join(root, filename)) if yamlpath in already_included: continue if process_yamlfile(tree, yamlpath, quiet): matches.append(yamlpath) return matches
def main(dpath, ppath, update, quiet): with open(dpath) as f: device = yaml.safe_load(f) if "_svd" not in device: print("Could not find _svd in device YAML, cannot proceed.") return device["_path"] = dpath matches = process_device(device, ppath, quiet) if matches: absdpath = svdpatch.abspath(sys.argv[0], dpath) common = os.path.commonprefix([absdpath] + matches) matches = [" - ../" + match[len(common):] for match in matches] if not quiet: print("\nMatched these new peripherals:") print("\n".join(matches)) else: print(dpath) print("\n".join(matches)) if update: print("Updating device YAML") with open(dpath, "a") as f: f.write("\n".join(matches)) f.write("\n") print() else: if not quiet: print("No new peripherals matched.\n")
def main(devices, output): print("Stage 1: Enumerating all fields in all devices") peripherals = {} for device_path in tqdm(glob.glob(os.path.join(devices, "*.yaml"))): device_name = os.path.splitext(os.path.basename(device_path))[0] with open(device_path, encoding='utf-8') as f: device = yaml.safe_load(f) device["_path"] = device_path if "_svd" not in device: raise RuntimeError("You must have an _svd key in the YAML file") svdpath = svdpatch.abspath(device_path, device["_svd"]) svd = ET.parse(svdpath) svdpatch.process_device(svd, device) for ptag in svd.iter('peripheral'): if "derivedFrom" in ptag.attrib: continue pname = ptag.find('name').text device_members = [] for rtag in ptag.iter('register'): rname = rtag.find('name').text roffset = rtag.find('addressOffset').text for ftag in rtag.iter('field'): fname = ftag.find('name').text foffset = ftag.find('bitOffset').text fwidth = ftag.find('bitWidth').text device_members.append("{}__{}_{}__{}_{}_{}".format( pname, roffset, rname, foffset, fwidth, fname)) if pname not in peripherals: peripherals[pname] = {} peripherals[pname][device_name] = device_members print("Stage 2: Inverting to find all devices for each field and merging") fields = {} merged_fields = {} for pname, devices in tqdm(peripherals.items()): fields[pname] = {} for device, device_fields in devices.items(): for fname in device_fields: if fname not in fields[pname]: fields[pname][fname] = set() fields[pname][fname].add(device) merged_fields[pname] = {} skip_fields = set() for field, devices in fields[pname].items(): if field in skip_fields: continue merged_key = [field] for field2, devices2 in fields[pname].items(): if field != field2 and devices == devices2: merged_key.append(field2) skip_fields.add(field2) merged_fields[pname][",".join(sorted(merged_key))] = devices print("Stage 3: Building tree of subsets") field_tree = {} for pname in tqdm(merged_fields): field_tree[pname] = {} # Build our dict of tree nodes for fieldset, devices in merged_fields[pname].items(): field_tree[pname][fieldset] = (devices, {}) # Function to take a given (fieldset: (devices, children)) # and dictionary of its siblings (including itself), # then move all siblings inside itself and recurse, # returning the list of all siblings moved inside itself. def treeify(fieldset, devices, children, siblings): # First find all subsets and move them into our children moved_siblings = [] for fieldset2, (devices2, children2) in siblings.items(): if fieldset2 != fieldset and devices2 < devices: children[fieldset2] = (devices2, children2) moved_siblings.append(fieldset2) # Remove all our new children from the parent list for fieldset2 in moved_siblings: del siblings[fieldset2] # Now treeify each new child moved_children = [] for fieldset2 in moved_siblings: if fieldset2 in moved_children: continue devices2, children2 = children[fieldset2] moved_children += treeify( fieldset2, devices2, children2, children) return moved_siblings # Form the tree of all these fieldsets fieldsets = list(field_tree[pname].keys()) moved_fieldsets = [] for fieldset in fieldsets: if fieldset in moved_fieldsets: continue devices, children = field_tree[pname][fieldset] moved_fieldsets += treeify( fieldset, devices, children, field_tree[pname]) # Now strip the device names from all but the leaves def strip_devices(siblings): fieldsets = list(siblings.keys()) for fieldset in fieldsets: devices, children = siblings[fieldset] if children: strip_devices(children) siblings[fieldset] = children else: siblings[fieldset] = list(devices) strip_devices(field_tree[pname]) print("Stage 4: Writing results JSON") with open(output, "w") as f: json.dump(field_tree, f, indent=2, sort_keys=True)