aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEric Kunze <eric.kunze@arm.com>2024-02-25 22:24:52 -0800
committerEric Kunze <eric.kunze@arm.com>2024-03-12 15:57:14 -0700
commit6dd341093507157aabbea00b90ca8902509cfd4f (patch)
tree26cb8ceb77dcf1dd3e57d990c3155246ab1efc6f /tools
parente6ee631e7a7bdc9d334f5dd1d0c30d639e40612b (diff)
downloadspecification-6dd341093507157aabbea00b90ca8902509cfd4f.tar.gz
Modify TOSA profiles
Create composable profiles and profile extensions. Define requirements for a TOSA implementation to fully implement at least one profile. Signed-off-by: Eric Kunze <eric.kunze@arm.com> Change-Id: I02cfb0171b2d227727f530cb29108b479206b25b
Diffstat (limited to 'tools')
-rw-r--r--tools/dictionary.dic1
-rwxr-xr-xtools/genspec.py84
-rw-r--r--tools/tosa.py49
3 files changed, 130 insertions, 4 deletions
diff --git a/tools/dictionary.dic b/tools/dictionary.dic
index 53377a0..e5a70a2 100644
--- a/tools/dictionary.dic
+++ b/tools/dictionary.dic
@@ -4,6 +4,7 @@ adoc
acc
ARGMAX
AsciiDoc
+BFloat
BILINEAR
bilinearly
bitwise
diff --git a/tools/genspec.py b/tools/genspec.py
index bdca32c..3865486 100755
--- a/tools/genspec.py
+++ b/tools/genspec.py
@@ -2,10 +2,25 @@
# Copyright (c) 2023-2024, ARM Limited.
# SPDX-License-Identifier: Apache-2.0
import os
+import re
+from functools import cmp_to_key
import tosa
+def compare_profiles(a, b):
+ if a.profiles[0] == b.profiles[0]:
+ return 1 if a.mode > b.mode else -1
+ if "EXT-" in a.profiles[0]:
+ if "EXT-" in b.profiles[0]:
+ return 1 if a.profiles[0] > b.profiles[0] else -1
+ else:
+ return 1
+ if "EXT-" in b.profiles[0]:
+ return -1
+ return 1 if a.profiles[0] > b.profiles[0] else -1
+
+
class TOSASpecAsciidocGenerator:
def __init__(self, spec):
self.spec = spec
@@ -73,12 +88,12 @@ class TOSASpecAsciidocGenerator:
if op.typesupports:
file.write("\n*Supported Data Types:*\n\n")
file.write("|===\n")
- header = "|Profile|Mode"
+ header = "|Profile/Extension|Mode"
for ty in op.types:
header += f"|{ty}"
file.write(header)
file.write("\n\n")
- for tysup in op.typesupports:
+ for tysup in sorted(op.typesupports, key=cmp_to_key(compare_profiles)):
profile = ", ".join(tysup.profiles) if tysup.profiles else "Any"
entry = f"|{profile}|{tysup.mode}"
for ty in op.types:
@@ -108,6 +123,28 @@ class TOSASpecAsciidocGenerator:
f.write(" draft")
f.write("\n")
+ # Generate profile table
+ with open(os.path.join(outdir, "profiles.adoc"), "w") as f:
+ f.write("|===\n")
+ f.write("|Profile|Name|Description|Specification Status\n\n")
+ for profile in self.spec.profiles:
+ f.write(
+ f"|{profile.profile}|{profile.name}|"
+ f"{profile.description}|{profile.status}\n"
+ )
+ f.write("|===\n")
+
+ # Generate profile table
+ with open(os.path.join(outdir, "profile_extensions.adoc"), "w") as f:
+ f.write("|===\n")
+ f.write("|Name|Description|Specification Status\n\n")
+ for profile_extension in self.spec.profile_extensions:
+ f.write(
+ f"|{profile_extension.name}|{profile_extension.description}"
+ f"|{profile_extension.status}\n"
+ )
+ f.write("|===\n")
+
# Generate level maximums table
with open(os.path.join(outdir, "levels.adoc"), "w") as f:
f.write("|===\n")
@@ -137,6 +174,49 @@ class TOSASpecAsciidocGenerator:
for enum in self.spec.enums:
self.generate_enum(enum, f)
+ all_operators = []
+ for group in self.spec.operatorgroups:
+ for op in group.operators:
+ all_operators.append(op)
+
+ # Generate profile operator appendix
+ with open(os.path.join(outdir, "profile_ops.adoc"), "w") as f:
+ f.write("=== Profiles\n")
+ for profile in self.spec.profiles:
+ f.write(f"==== {profile.profile}\n")
+ f.write(f"{profile.description}\n\n")
+ f.write(f"Status: {profile.status}\n")
+ f.write("|===\n")
+ f.write("|Operator|mode\n\n")
+ for op in sorted(all_operators, key=lambda o: o.name):
+ if op.typesupports:
+ for tysup in op.typesupports:
+ if profile.name in tysup.profiles:
+ f.write(f"|{op.name}|{tysup.mode}\n")
+ f.write("|===\n")
+
+ f.write("=== Profile Extensions\n")
+ for pext in self.spec.profile_extensions:
+ f.write(f"==== {pext.name} extension\n")
+ f.write(f"{pext.description}\n\n")
+ f.write(f"Status: {pext.status}\n")
+ f.write("|===\n")
+ f.write("|Operator|mode|note\n\n")
+ for op in sorted(all_operators, key=lambda o: o.name):
+ if op.typesupports:
+ for tysup in op.typesupports:
+ for profile in tysup.profiles:
+ if profile.find(pext.name) != -1:
+ note = ""
+ m = re.match(r"(.*) and (.*)", profile)
+ if m:
+ if m[1] == pext.name:
+ note = f"If {m[2]} is also supported"
+ else:
+ note = f"If {m[1]} is also supported"
+ f.write(f"|{op.name}|{tysup.mode}|{note}\n")
+ f.write("|===\n")
+
if __name__ == "__main__":
import argparse
diff --git a/tools/tosa.py b/tools/tosa.py
index 803e478..e70b297 100644
--- a/tools/tosa.py
+++ b/tools/tosa.py
@@ -31,6 +31,23 @@ class TOSAOperatorArgumentCategory:
self.profiles = profiles
+class TOSAProfile:
+ def __init__(self, profile, name, description, status):
+ self.profile = profile
+ self.name = name
+ self.description = description
+ self.status = status
+ self.ops = []
+
+
+class TOSAProfileExtension:
+ def __init__(self, name, description, status):
+ self.name = name
+ self.description = description
+ self.status = status
+ self.ops = []
+
+
class TOSAEnum:
def __init__(self, name, description, values):
self.name = name
@@ -95,6 +112,8 @@ class TOSASpec:
def __init__(self, xmlpath):
tree = ET.parse(xmlpath)
self.xmlroot = tree.getroot()
+ self.profiles = []
+ self.profile_extensions = []
self.levels = []
self.operatorgroups = []
self.enums = []
@@ -102,6 +121,12 @@ class TOSASpec:
def __load_spec(self):
self.__load_version()
+ for profile in self.xmlroot.findall("./profiles/profile"):
+ self.profiles.append(self.__load_profile(profile))
+ for profile_ext in self.xmlroot.findall(
+ "./profile_extensions/profile_extension"
+ ):
+ self.profile_extensions.append(self.__load_profile_extension(profile_ext))
for level in self.xmlroot.findall("./levels/level"):
self.levels.append(self.__load_level(level))
for group in self.xmlroot.findall("./operators/operatorgroup"):
@@ -119,6 +144,19 @@ class TOSASpec:
else:
self.version_is_draft = False
+ def __load_profile(self, xml_profile):
+ profile = xml_profile.get("profile")
+ name = xml_profile.get("name")
+ description = xml_profile.get("description")
+ status = xml_profile.get("status")
+ return TOSAProfile(profile, name, description, status)
+
+ def __load_profile_extension(self, ext):
+ name = ext.get("name")
+ description = ext.get("description")
+ status = ext.get("status")
+ return TOSAProfileExtension(name, description, status)
+
def __load_level(self, level):
name = level.get("name")
desc = level.text.strip()
@@ -155,10 +193,17 @@ class TOSASpec:
for tysup in op.findall("typesupport"):
tsmode = tysup.get("mode")
tsmap = {}
- profiles = tysup.findall("profile")
+ profiles = tysup.findall("op_profile")
tsprofiles = []
for p in profiles:
- tsprofiles.append(p.get("name"))
+ tsp_name = p.get("name")
+ and_name = p.get("and_name")
+ if and_name is not None:
+ if and_name < tsp_name:
+ tsp_name = f"{and_name} and {tsp_name}"
+ else:
+ tsp_name = f"{tsp_name} and {and_name}"
+ tsprofiles.append(tsp_name)
for ty in types:
tsmap[ty] = tysup.get(ty)
typesupports.append(TOSAOperatorDataTypeSupport(tsmode, tsmap, tsprofiles))