예제 #1
0
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
예제 #2
0
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")
예제 #3
0
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)