From 981eb3906c47a5318c2d62da53b7df140cacc03f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 23 Aug 2021 15:53:20 -0500 Subject: [PATCH 1/6] [Hexagon] Rework tvm.target.hexagon() interface Make the tvm.target.hexagon() function take most options as keyword parameters. This will allow adding additional parameters without changing the interface. No changes are required to existing code, except for changing positional parameters following the CPU version to keyword parameters, and updating the names of the keyword parameters: sim_args -> sim_options, llvm_args -> llvm_options, although the old names will be accepted for the time being. --- python/tvm/target/target.py | 136 +++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index 559e7b3b28d3..b85f5be4f1c2 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -413,79 +413,116 @@ def bifrost(model="unknown", options=None): return Target(" ".join(["opencl"] + opts)) -def hexagon(cpu_ver="v66", sim_args=None, llvm_args=None, hvx=128): +def hexagon(cpu_ver="v66", **kwargs): """Returns a Hexagon target. Parameters ---------- - cpu_ver : str + cpu_ver : str (default: "v66") CPU version used for code generation. Not all allowed cpu str will be valid, LLVM will throw an error. - sim_args : str or list of str + + Recognized keyword parameters + ----------------------------- + hvx : int (default: 128) + Size of HVX vector in bytes. Value of 0 disables HVX codegen. + sim_options : str or list of str (default: None) User defined sim arguments. CPU version defaults to cpu_ver. Otherwise, separate versions are used for codegen and sim. Not all allowed cpu strings will be valid, simulator will throw an error if invalid. Does not affect codegen. - llvm_args : str or list of str + llvm_options : str or list of str (default: None) User defined compiler arguments. - hvx : int - Size of hvx register. Value of 0 indicates disabled hvx. """ + + # Some of the target parameters correspond to target kind attributes + # listed in src/target/target_kind.cc. For those parameters, their + # names follow the attribute names with the exception of '_' being used + # in place of '-'. + # Example compiler arguments # llvm -mtriple=hexagon -mcpu=hexagonv66 -mattr=+hvxv66,+hvx-length128b # Check for valid codegen cpu - valid_hex = ["v60", "v62", "v65", "v66", "v67", "v67t"] + valid_hex = ["v60", "v62", "v65", "v66", "v67", "v67t", "v68"] try: cpu_ver = cpu_ver[cpu_ver.index("v") :].lower() - assert 3 <= len(cpu_ver) <= 4 + assert cpu_ver in valid_hex except: msg = "{} is not a valid Hexagon version\nvalid versions include {}" raise ValueError(msg.format(cpu_ver, valid_hex)) from None - assert hvx in [0, 64, 128] - - # Target string - def create_target(cpu_ver): + args = { + 'hvx' : 128, + 'sim_options' : None, + 'llvm_options' : None, + } + args.update(kwargs) + + # Warn about obsolete parameter names. + if args.get("sim_args"): + msg = "The keyword parameter 'sim_args' is deprecated, use 'sim_options' instead" + warnings.warn(msg, stacklevel=2) + args.update({"sim_options": args["sim_args"]}) + if args.get("llvm_args"): + msg = "The keyword parameter 'llvm_args' is deprecated, use 'llvm_options' instead" + warnings.warn(msg, stacklevel=2) + args.update({"llvm_options": args["llvm_args"]}) + + # LLVM target string + def create_llvm_target(cpu_ver, args): + """ Create LLVM target string. """ target = " -mtriple=hexagon" mcpu = " -mcpu=hexagon" + cpu_ver - mattr = "" - # HVX enable - if hvx: - mattr = " -mattr=+hvx" + cpu_ver + ",+hvx-length" + str(hvx) + "b" - return target + mcpu + mattr - - # Simulator string - def create_sim(cpu_ver, sim_args): - def validate_hvx_length(codegen_hvx, sim_args): - if sim_args and "--hvx_length" in sim_args: + + # Process the options that affect target features and return the + # target feature string. + def create_target_features(args): + tfs = [] + if args["hvx"] > 0: + valid_hvx = [0, 64, 128] + if not args["hvx"] in valid_hvx: + raise ValueError("Invalid hvx value, should be one of " + str(valid_hvx)) + tfs += ["+hvx" + cpu_ver, "+hvx-length" + str(args["hvx"]) + "b"] + else: + tfs += ["-hvx"] + return "-mattr=" + ",".join(tfs) if tfs else "" + + return target + mcpu + " " + create_target_features(args) + + # Simulator options string + def create_sim_options(cpu_ver, args): + """ Create simulator option string. """ + def validate_hvx_length(codegen_hvx, sim_options): + """ Check that HVX length options match between codegen and simulator. """ + if sim_options and "--hvx_length" in sim_options: # If --hvx_length was specified, check HVX length of sim # vs codegen - i = sim_args.index("hvx_length") + len("hvx_length") + 1 - sim_hvx = sim_args[i : i + 3] + i = sim_options.index("hvx_length") + len("hvx_length") + 1 + sim_hvx = sim_options[i : i + 3] if sim_hvx != str(codegen_hvx): - print( - "WARNING: sim hvx {} and codegen hvx {} mismatch!".format( - sim_hvx, codegen_hvx - ) - ) + msg = "sim hvx {} and codegen hvx {} mismatch!".format(sim_hvx, codegen_hvx) + # Set the stacklevel to the tvm.target.hexagon() call. + warnings.warn(msg, stacklevel=4) elif codegen_hvx != 0: # If --hvx_length was not given, add it if HVX is enabled - sim_args = sim_args + " " if isinstance(sim_args, str) else "" - sim_args += "--hvx_length " + str(codegen_hvx) - return sim_args or "" + sim_options = sim_options + " " if isinstance(sim_options, str) else "" + sim_options += "--hvx_length " + str(codegen_hvx) + return sim_options or "" - if not sim_args: - return cpu_ver + " " + validate_hvx_length(hvx, sim_args) + hvx = args["hvx"] + sim_options = args["sim_options"] + if not sim_options: + return cpu_ver + " " + validate_hvx_length(hvx, sim_options) sim_cpu = cpu_ver + " " # Add user defined args - if isinstance(sim_args, list): - sim_args = " ".join(sim_args) + if isinstance(sim_options, list): + sim_options = " ".join(sim_options) # Check for supplied sim cpu version - if "v6" in sim_args: + if "v6" in sim_options: sim_cpu = "" # Regex match for allowed cpus @@ -494,13 +531,13 @@ def validate_hvx_length(codegen_hvx, sim_args): + r"(?Pv6[25678])(?P[a-z])?" + r"(?P_[0-9]+)?(?P_rev[0-9])?\s?(?P--.*)?" ) - m = re.match(valid_cpu_str_regex, sim_args.lower()) + m = re.match(valid_cpu_str_regex, sim_options.lower()) if not m: - raise ValueError('Invalid simulator argument string "{}"'.format(sim_args)) + raise ValueError('Invalid simulator argument string "{}"'.format(sim_options)) # Parse options into correct order cpu_attr = {x: str(m.groupdict()[x] or "") for x in m.groupdict()} - sim_args = ( + sim_options = ( cpu_attr["base_version"] + cpu_attr["sub_version"] + cpu_attr["l2_size"] @@ -510,23 +547,26 @@ def validate_hvx_length(codegen_hvx, sim_args): + cpu_attr["post"] ) - return sim_cpu + " " + validate_hvx_length(hvx, sim_args) + return sim_cpu + " " + validate_hvx_length(hvx, sim_options) + + # LLVM options string + def create_llvm_options(cpu_ver, args): # pylint: disable=unused-argument + """ Create LLVM options string. """ + llvm_options = args["llvm_options"] - # LLVM string - def create_llvm(llvm_args): # TVM's option parser doesn't allow '=' in values, but '=' can # appear in LLVM flags. Replace it with '@', since it's unlikely # that '@' will be used in another context. - if llvm_args is None or len(llvm_args.replace(" ", "")) == 0: + if llvm_options is None or len(llvm_options.replace(" ", "")) == 0: return "" - args = [s.replace("=", "@") for s in llvm_args.split()] + args = [s.replace("=", "@") for s in llvm_options.split()] return "--llvm-options=" + ",".join(args) # Sim args - os.environ["HEXAGON_SIM_ARGS"] = create_sim(cpu_ver, sim_args) + os.environ["HEXAGON_SIM_ARGS"] = create_sim_options(cpu_ver, args) - target_str = create_target(cpu_ver) - llvm_str = create_llvm(llvm_args) + target_str = create_llvm_target(cpu_ver, args) + llvm_str = create_llvm_options(cpu_ver, args) args_list = target_str.split() + llvm_str.split() return Target(" ".join(["hexagon"] + args_list)) From c3948b2fc409855f384e92e32ed00b25b94eb00e Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 23 Aug 2021 17:16:50 -0500 Subject: [PATCH 2/6] formatting --- python/tvm/target/target.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index b85f5be4f1c2..f112b1225c48 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -453,9 +453,9 @@ def hexagon(cpu_ver="v66", **kwargs): raise ValueError(msg.format(cpu_ver, valid_hex)) from None args = { - 'hvx' : 128, - 'sim_options' : None, - 'llvm_options' : None, + 'hvx': 128, + 'sim_options': None, + 'llvm_options': None, } args.update(kwargs) @@ -472,6 +472,7 @@ def hexagon(cpu_ver="v66", **kwargs): # LLVM target string def create_llvm_target(cpu_ver, args): """ Create LLVM target string. """ + target = " -mtriple=hexagon" mcpu = " -mcpu=hexagon" + cpu_ver @@ -493,8 +494,8 @@ def create_target_features(args): # Simulator options string def create_sim_options(cpu_ver, args): """ Create simulator option string. """ + def validate_hvx_length(codegen_hvx, sim_options): - """ Check that HVX length options match between codegen and simulator. """ if sim_options and "--hvx_length" in sim_options: # If --hvx_length was specified, check HVX length of sim # vs codegen @@ -550,8 +551,9 @@ def validate_hvx_length(codegen_hvx, sim_options): return sim_cpu + " " + validate_hvx_length(hvx, sim_options) # LLVM options string - def create_llvm_options(cpu_ver, args): # pylint: disable=unused-argument + def create_llvm_options(cpu_ver, args): # pylint: disable=unused-argument """ Create LLVM options string. """ + llvm_options = args["llvm_options"] # TVM's option parser doesn't allow '=' in values, but '=' can From 432df9523e2339ddec39291e911f3c0ce31c3e86 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 23 Aug 2021 18:18:07 -0500 Subject: [PATCH 3/6] change ' to " --- python/tvm/target/target.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index f112b1225c48..f2c0c06c018d 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -453,9 +453,9 @@ def hexagon(cpu_ver="v66", **kwargs): raise ValueError(msg.format(cpu_ver, valid_hex)) from None args = { - 'hvx': 128, - 'sim_options': None, - 'llvm_options': None, + "hvx": 128, + "sim_options": None, + "llvm_options": None, } args.update(kwargs) From 51894c3a32e66b0e538e0385d6114b6ceceae5b3 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 25 Aug 2021 09:50:45 -0500 Subject: [PATCH 4/6] Rename 'args' to 'config' for clarity --- python/tvm/target/target.py | 41 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index f2c0c06c018d..b55cbd3c3dbb 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -452,25 +452,26 @@ def hexagon(cpu_ver="v66", **kwargs): msg = "{} is not a valid Hexagon version\nvalid versions include {}" raise ValueError(msg.format(cpu_ver, valid_hex)) from None - args = { + # Target configuration: + config = { "hvx": 128, "sim_options": None, "llvm_options": None, } - args.update(kwargs) + config.update(kwargs) # Warn about obsolete parameter names. - if args.get("sim_args"): + if config.get("sim_args"): msg = "The keyword parameter 'sim_args' is deprecated, use 'sim_options' instead" warnings.warn(msg, stacklevel=2) - args.update({"sim_options": args["sim_args"]}) - if args.get("llvm_args"): + config.update({"sim_options": config["sim_args"]}) + if config.get("llvm_args"): msg = "The keyword parameter 'llvm_args' is deprecated, use 'llvm_options' instead" warnings.warn(msg, stacklevel=2) - args.update({"llvm_options": args["llvm_args"]}) + config.update({"llvm_options": config["llvm_args"]}) # LLVM target string - def create_llvm_target(cpu_ver, args): + def create_llvm_target(cpu_ver, config): """ Create LLVM target string. """ target = " -mtriple=hexagon" @@ -478,21 +479,21 @@ def create_llvm_target(cpu_ver, args): # Process the options that affect target features and return the # target feature string. - def create_target_features(args): + def create_target_features(config): tfs = [] - if args["hvx"] > 0: + if config["hvx"] > 0: valid_hvx = [0, 64, 128] - if not args["hvx"] in valid_hvx: + if not config["hvx"] in valid_hvx: raise ValueError("Invalid hvx value, should be one of " + str(valid_hvx)) - tfs += ["+hvx" + cpu_ver, "+hvx-length" + str(args["hvx"]) + "b"] + tfs += ["+hvx" + cpu_ver, "+hvx-length" + str(config["hvx"]) + "b"] else: tfs += ["-hvx"] return "-mattr=" + ",".join(tfs) if tfs else "" - return target + mcpu + " " + create_target_features(args) + return target + mcpu + " " + create_target_features(config) # Simulator options string - def create_sim_options(cpu_ver, args): + def create_sim_options(cpu_ver, config): """ Create simulator option string. """ def validate_hvx_length(codegen_hvx, sim_options): @@ -511,8 +512,8 @@ def validate_hvx_length(codegen_hvx, sim_options): sim_options += "--hvx_length " + str(codegen_hvx) return sim_options or "" - hvx = args["hvx"] - sim_options = args["sim_options"] + hvx = config["hvx"] + sim_options = config["sim_options"] if not sim_options: return cpu_ver + " " + validate_hvx_length(hvx, sim_options) @@ -551,10 +552,10 @@ def validate_hvx_length(codegen_hvx, sim_options): return sim_cpu + " " + validate_hvx_length(hvx, sim_options) # LLVM options string - def create_llvm_options(cpu_ver, args): # pylint: disable=unused-argument + def create_llvm_options(cpu_ver, config): # pylint: disable=unused-argument """ Create LLVM options string. """ - llvm_options = args["llvm_options"] + llvm_options = config["llvm_options"] # TVM's option parser doesn't allow '=' in values, but '=' can # appear in LLVM flags. Replace it with '@', since it's unlikely @@ -565,10 +566,10 @@ def create_llvm_options(cpu_ver, args): # pylint: disable=unused-argument return "--llvm-options=" + ",".join(args) # Sim args - os.environ["HEXAGON_SIM_ARGS"] = create_sim_options(cpu_ver, args) + os.environ["HEXAGON_SIM_ARGS"] = create_sim_options(cpu_ver, config) - target_str = create_llvm_target(cpu_ver, args) - llvm_str = create_llvm_options(cpu_ver, args) + target_str = create_llvm_target(cpu_ver, config) + llvm_str = create_llvm_options(cpu_ver, config) args_list = target_str.split() + llvm_str.split() return Target(" ".join(["hexagon"] + args_list)) From 89219ab1b84b0708899665ac83635f10c06ff45f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 25 Aug 2021 09:53:13 -0500 Subject: [PATCH 5/6] Use 'strip' instad of 'replace' --- python/tvm/target/target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index b55cbd3c3dbb..aa9226101b52 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -560,7 +560,7 @@ def create_llvm_options(cpu_ver, config): # pylint: disable=unused-argument # TVM's option parser doesn't allow '=' in values, but '=' can # appear in LLVM flags. Replace it with '@', since it's unlikely # that '@' will be used in another context. - if llvm_options is None or len(llvm_options.replace(" ", "")) == 0: + if llvm_options is None or len(llvm_options.strip()) == 0: return "" args = [s.replace("=", "@") for s in llvm_options.split()] return "--llvm-options=" + ",".join(args) From fa0035249273c5da6d36881e00dfd176c39ef713 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 25 Aug 2021 10:00:32 -0500 Subject: [PATCH 6/6] Restart build