From 7733b942246cfbfa354328d28a8a469e1c135f37 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Thu, 12 Sep 2019 17:08:43 -0500 Subject: [PATCH] sanitycheck: Add functions to query device tree for filters Add the following functions to allow filtering based on device tree dt_compat_enabled(compat) - Returns true if a device tree node compatible matches 'compat' and the node is enabled. dt_alias_exists(alias) - Returns true if a device tree node exists with 'alias' and the node is enabled. dt_compat_enabled_with_alias - Returns true if a device tree node compatible matches 'compat' and the node has 'alias' and the node is enabled. Signed-off-by: Kumar Gala --- scripts/sanity_chk/expr_parser.py | 47 ++++++++++++++++++++++++++----- scripts/sanitycheck | 17 +++++++---- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/scripts/sanity_chk/expr_parser.py b/scripts/sanity_chk/expr_parser.py index b28af219a39..b0c87208fdd 100644 --- a/scripts/sanity_chk/expr_parser.py +++ b/scripts/sanity_chk/expr_parser.py @@ -134,6 +134,20 @@ def p_expr_single(p): """expr : SYMBOL""" p[0] = ("exists", p[1]) +def p_func(p): + """expr : SYMBOL OPAREN arg_intr CPAREN""" + p[0] = [p[1]] + p[0].append(p[3]) + +def p_arg_intr_single(p): + """arg_intr : const""" + p[0] = [p[1]] + +def p_arg_intr_mult(p): + """arg_intr : arg_intr COMMA const""" + p[0] = copy.copy(p[1]) + p[0].append(p[3]) + def p_list(p): """list : OBRACKET list_intr CBRACKET""" p[0] = p[2] @@ -182,13 +196,13 @@ def ast_sym_int(ast, env): return int(v, 10) return 0 -def ast_expr(ast, env): +def ast_expr(ast, env, edt): if ast[0] == "not": - return not ast_expr(ast[1], env) + return not ast_expr(ast[1], env, edt) elif ast[0] == "or": - return ast_expr(ast[1], env) or ast_expr(ast[2], env) + return ast_expr(ast[1], env, edt) or ast_expr(ast[2], env, edt) elif ast[0] == "and": - return ast_expr(ast[1], env) and ast_expr(ast[2], env) + return ast_expr(ast[1], env, edt) and ast_expr(ast[2], env, edt) elif ast[0] == "==": return ast_sym(ast[1], env) == ast[2] elif ast[0] == "!=": @@ -207,10 +221,29 @@ def ast_expr(ast, env): return bool(ast_sym(ast[1], env)) elif ast[0] == ":": return bool(re.match(ast[2], ast_sym(ast[1], env))) + elif ast[0] == "dt_compat_enabled": + compat = ast[1][0] + for node in edt.nodes: + if compat in node.compats and node.enabled: + return True + return False + elif ast[0] == "dt_alias_exists": + alias = ast[1][0] + for node in edt.nodes: + if alias in node.aliases and node.enabled: + return True + return False + elif ast[0] == "dt_compat_enabled_with_alias": + compat = ast[1][0] + alias = ast[1][1] + for node in edt.nodes: + if node.enabled and alias in node.aliases and node.matching_compat == compat: + return True + return False mutex = threading.Lock() -def parse(expr_text, env): +def parse(expr_text, env, edt): """Given a text representation of an expression in our language, use the provided environment to determine whether the expression is true or false""" @@ -222,7 +255,7 @@ def parse(expr_text, env): finally: mutex.release() - return ast_expr(ast, env) + return ast_expr(ast, env, edt) # Just some test code if __name__ == "__main__": @@ -244,4 +277,4 @@ if __name__ == "__main__": parser = yacc.yacc() print(parser.parse(line)) - print(parse(line, local_env)) + print(parse(line, local_env, None)) diff --git a/scripts/sanitycheck b/scripts/sanitycheck index 7dfa8b77ab4..07739902cff 100755 --- a/scripts/sanitycheck +++ b/scripts/sanitycheck @@ -199,6 +199,13 @@ from itertools import islice from pathlib import Path from distutils.spawn import find_executable +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") +if not ZEPHYR_BASE: + sys.exit("$ZEPHYR_BASE environment variable undefined") + +sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts", "dts")) +import edtlib + import logging @@ -209,11 +216,6 @@ report_lock = threading.Lock() log_format = "%(levelname)s %(name)s::%(module)s.%(funcName)s():%(lineno)d: %(message)s" logging.basicConfig(format=log_format, level=30) -ZEPHYR_BASE = os.environ.get("ZEPHYR_BASE") -if not ZEPHYR_BASE: - sys.stderr.write("$ZEPHYR_BASE environment variable undefined.\n") - exit(1) - # Use this for internal comparisons; that's what canonicalization is # for. Don't use it when invoking other components of the build system # to avoid confusing and hard to trace inconsistencies in error messages @@ -1902,7 +1904,10 @@ class FilterBuilder(CMake): if self.testcase and self.testcase.tc_filter: try: - res = expr_parser.parse(self.testcase.tc_filter, filter_data) + dts_path = os.path.join(self.build_dir, "zephyr", self.platform.name + ".dts.pre.tmp") + edt = edtlib.EDT(dts_path, [os.path.join(ZEPHYR_BASE, "dts", "bindings")]) + res = expr_parser.parse(self.testcase.tc_filter, filter_data, edt) + except (ValueError, SyntaxError) as se: sys.stderr.write( "Failed processing %s\n" % self.testcase.yamlfile)