+from openpower.util import log
+from pathlib import Path
+import gzip
+import json
+import sys
+from hashlib import sha256
+from functools import lru_cache
+
+# output-for-v0.2.0-7-g95fdd1c.json.gz generated from:
+# https://salsa.debian.org/Kazan-team/power-instruction-analyzer/-/commit/95fdd1c4edbd91c0a02b772ba02aa2045101d2b0
+# running on POWER9
+PIA_OUTPUT_URL = "https://ftp.libre-soc.org/power-instruction-analyzer/output-for-v0.2.0-7-g95fdd1c.json.gz"
+PIA_OUTPUT_SHA256 = "2ad50464eb6c9b6bf2dad2ee16b6820a34024bc008ea86818845cf14f7f457ad"
+PIA_OUTPUT_PATH = Path(__file__).parent / PIA_OUTPUT_URL.rpartition('/')[2]
+
+
+def download_pia_output():
+ from urllib.request import urlopen
+ from shutil import copyfileobj
+ with PIA_OUTPUT_PATH.open("wb") as f:
+ print(f"downloading {PIA_OUTPUT_URL} to {PIA_OUTPUT_PATH}",
+ file=sys.stderr, flush=True)
+ with urlopen(PIA_OUTPUT_URL) as response:
+ copyfileobj(response, f)
+
+
+def read_pia_output(filter_fn):
+ tried_download = False
+ while True:
+ try:
+ file_bytes = PIA_OUTPUT_PATH.read_bytes()
+ digest = sha256(file_bytes).hexdigest()
+ if digest != PIA_OUTPUT_SHA256:
+ raise Exception(f"{PIA_OUTPUT_PATH} has wrong hash, expected "
+ f"{PIA_OUTPUT_SHA256} got {digest}")
+ file_bytes = gzip.decompress(file_bytes)
+ test_cases = json.loads(file_bytes)['test_cases']
+ return list(filter(filter_fn, test_cases))
+ except:
+ if tried_download:
+ raise
+ pass
+ tried_download = True
+ download_pia_output()
+
+
+@lru_cache(maxsize=None)
+def get_addmeo_subfmeo_reference_cases():
+ return read_pia_output(lambda i: i['instr'] in ("addmeo", "subfmeo"))
+
+
+def check_addmeo_subfmeo_matches_reference(instr, case_filter, out):
+ case_filter = {
+ 'instr': instr,
+ 'ra': '0x0', 'ca': False, 'ca32': False,
+ 'so': False, 'ov': False, 'ov32': False,
+ **case_filter
+ }
+ for case in get_addmeo_subfmeo_reference_cases():
+ skip = False
+ for k, v in case_filter.items():
+ if case[k] != v:
+ skip = True
+ break
+ if skip:
+ continue
+ reference_outputs = case['native_outputs']
+ for k, v in out.items():
+ assert reference_outputs[k] == v, (
+ f"{instr} outputs don't match reference:\n"
+ f"case_filter={case_filter}\nout={out}\n"
+ f"reference_outputs={reference_outputs}")
+ log(f"PIA reference successfully matched: {case_filter}")
+ return True
+ log(f"PIA reference not found: {case_filter}")
+ return False