From 68027dac7e453c3fdfdc24f0350650fe5c06a487 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Thu, 26 Oct 2023 13:59:16 +0300 Subject: [PATCH] python --- CHANGELOG-python.md | 2 ++ src/patch/peripheral.rs | 5 +++++ svdtools/patch.py | 48 ++++++++++++++++++++++++++++++++++------- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/CHANGELOG-python.md b/CHANGELOG-python.md index d329d220..15ee05c1 100644 --- a/CHANGELOG-python.md +++ b/CHANGELOG-python.md @@ -5,6 +5,8 @@ This changelog tracks the Python `svdtools` project. See ## [Unreleased] +* Ignore rule if starts with "?@" and no matched instances + ## [v0.1.26] 2023-03-28 * Bump python to 3.9 to fix CI diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index 4f69e0cb..22e94f96 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -1355,6 +1355,11 @@ fn collect_in_cluster( } rdict.insert(rspec.to_string(), registers); } + if rdict.is_empty() { + return Err(anyhow!( + "{path}: registers cannot be collected into {cname} cluster. No matches found" + )); + } let address_offset = rdict .values() .min_by_key(|rs| rs[0].address_offset) diff --git a/svdtools/patch.py b/svdtools/patch.py index ad2e55bc..f522cd9e 100644 --- a/svdtools/patch.py +++ b/svdtools/patch.py @@ -56,6 +56,13 @@ def dict_constructor(loader, node, deep=False): yaml.add_constructor(_mapping_tag, dict_constructor, yaml.SafeLoader) +def get_spec(spec): + if spec.startswith("?@"): + return spec[2:], True + else: + return spec, False + + def matchname(name, spec): """Check if name matches against a specification.""" if spec.startswith("_"): @@ -646,6 +653,7 @@ def clear_fields(self, pspec): def process_peripheral(self, pspec, peripheral, update_fields=True): """Work through a peripheral, handling all registers.""" # Find all peripherals that match the spec + pspec, ignore = get_spec(pspec) pcount = 0 for ptag in self.iter_peripherals(pspec): pcount += 1 @@ -763,7 +771,7 @@ def process_peripheral(self, pspec, peripheral, update_fields=True): cluster = peripheral["_clusters"][cspec] p.process_cluster(cspec, cluster, update_fields) - if pcount == 0: + if not ignore and pcount == 0: raise MissingPeripheralError(f"Could not find {pspec}") @@ -1019,6 +1027,7 @@ def strip(self, substr, strip_end=False): def collect_in_array(self, rspec, rmod): """Collect same registers in peripheral into register array.""" registers = [] + rspec, ignore = get_spec(rspec) li, ri = spec_ind(rspec) for rtag in list(self.iter_registers(rspec)): rname = rtag.findtext("name") @@ -1031,6 +1040,8 @@ def collect_in_array(self, rspec, rmod): ) dim = len(registers) if dim == 0: + if ignore: + return raise SvdPatchError( "{}: registers {} not found".format(self.ptag.findtext("name"), rspec) ) @@ -1087,6 +1098,7 @@ def collect_in_cluster(self, cname, cmod): check = True rspecs = [r for r in cmod if r != "description"] for rspec in rspecs: + rspec, ignore = get_spec(rspec) registers = [] for rtag, match_rspec in list(self.iter_registers_with_matches(rspec)): rname = rtag.findtext("name") @@ -1098,14 +1110,17 @@ def collect_in_cluster(self, cname, cmod): int(rtag.findtext("addressOffset"), 0), ] ) + if len(registers) == 0: + if ignore: + continue + raise SvdPatchError( + "{}: registers {rspec} not found".format(self.ptag.findtext("name")) + ) registers = sorted(registers, key=lambda r: r[2]) rdict[rspec] = registers bitmasks = [Register(r[0]).get_bitmask() for r in registers] if first: dim = len(registers) - if dim == 0: - check = False - break dimIndex = ",".join([r[1] for r in registers]) offsets = [r[2] for r in registers] dimIncrement = 0 @@ -1127,6 +1142,12 @@ def collect_in_cluster(self, cname, cmod): check = False break first = False + if not rdict: + raise SvdPatchError( + "{}: registers cannot be collected into {} cluster. No matches found".format( + self.ptag.findtext("name"), cname + ) + ) if not check: raise SvdPatchError( "{}: registers cannot be collected into {} cluster".format( @@ -1176,6 +1197,7 @@ def clear_fields(self, rspec): def process_register(self, rspec, register, update_fields=True): """Work through a register, handling all fields.""" # Find all registers that match the spec + rspec, ignore = get_spec(rspec) pname = self.ptag.find("name").text rcount = 0 for rtag in self.iter_registers(rspec): @@ -1228,7 +1250,7 @@ def process_register(self, rspec, register, update_fields=True): for fspec in register.get("_array", {}): fmod = register["_array"][fspec] r.collect_fields_in_array(fspec, fmod) - if rcount == 0: + if not ignore and rcount == 0: raise MissingRegisterError(f"Could not find {pname}:{rspec}") def process_cluster_tag( @@ -1266,12 +1288,13 @@ def process_cluster( assert isinstance(cspec, str) assert isinstance(cluster, OrderedDict) assert isinstance(update_fields, bool) + cspec, ignore = get_spec(cspec) # Find all clusters that match the spec ccount = 0 for ctag in self.iter_clusters(cspec): self.process_cluster_tag(ctag, cluster, update_fields) ccount += 1 - if ccount == 0: + if not ignore and ccount == 0: raise MissingClusterError(f"Could not find {self.name}:{cspec}") @@ -1501,6 +1524,7 @@ def merge_fields(self, key, value): def collect_fields_in_array(self, fspec, fmod): """Collect same fields in peripheral into register array.""" fields = [] + fspec, ignore = get_spec(fspec) li, ri = spec_ind(fspec) for ftag in list(self.iter_fields(fspec)): fname = ftag.findtext("name") @@ -1509,6 +1533,8 @@ def collect_fields_in_array(self, fspec, fmod): ) dim = len(fields) if dim == 0: + if ignore: + return raise SvdPatchError( "{}: fields {} not found".format(self.rtag.findtext("name"), fspec) ) @@ -1559,8 +1585,11 @@ def split_fields(self, fspec, fsplit): Split all fspec in rtag. Name and description can be customized with %s as a placeholder to the iterator value. """ + fspec, ignore = get_spec(fspec) fields = list(self.iter_fields(fspec)) if len(fields) == 0: + if ignore: + return rname = self.rtag.find("name").text raise RegisterMergeError( f"Could not find any fields to split {rname}.{fspec}" @@ -1666,6 +1695,8 @@ def process_field_enum(self, pname, fspec, field, usage="read-write"): field = field["_replace_enum"] replace_if_exists = True + fspec, ignore = get_spec(fspec) + derived, enum, enum_name, enum_usage = None, None, None, None for ftag in sorted_fields(list(self.iter_fields(fspec))): if "_derivedFrom" in field: @@ -1719,17 +1750,18 @@ def process_field_enum(self, pname, fspec, field, usage="read-write"): derived = enum_name else: ftag.append(make_derived_enumerated_values(derived)) - if derived is None: + if not ignore and derived is None: rname = self.rtag.find("name").text raise MissingFieldError(f"Could not find {pname}:{rname}.{fspec}") def process_field_range(self, pname, fspec, field): """Add a writeConstraint range given by field to all fspec in rtag.""" + fspec, ignore = get_spec(fspec) set_any = False for ftag in self.iter_fields(fspec): ftag.append(make_write_constraint(field)) set_any = True - if not set_any: + if not ignore and not set_any: rname = self.rtag.find("name").text raise MissingFieldError(f"Could not find {pname}:{rname}.{fspec}")