enhanced YAML output to include all kernel objects and no ruamel.yaml-specific data types

This commit is contained in:
JanLJL
2023-08-15 14:01:11 +02:00
parent b50bc9ba1f
commit ab10febe74
3 changed files with 54 additions and 7 deletions

View File

@@ -8,6 +8,7 @@ import re
from datetime import datetime as dt from datetime import datetime as dt
from osaca.semantics import INSTR_FLAGS, ArchSemantics, KernelDG, MachineModel from osaca.semantics import INSTR_FLAGS, ArchSemantics, KernelDG, MachineModel
from osaca.parser import AttrDict
def _get_version(*file_paths): def _get_version(*file_paths):
@@ -209,6 +210,23 @@ class Frontend(object):
length_warning=False, length_warning=False,
lcd_warning=False, lcd_warning=False,
): ):
"""
Create a dictionary of the full analysis for machine-readable output.
:param kernel: kernel to report on
:type kernel: list
:param kernel_dg: directed graph containing CP and LCD
:type kernel_dg: :class:`~osaca.semantics.KernelDG`
:param arch_warning: flag for additional user warning to specify micro-arch
:type arch_warning: boolean, optional
:param length_warning: flag for additional user warning to specify kernel length with
--lines
:type length_warning: boolean, optional
:param lcd_warning: flag for additional user warning due to LCD analysis timed out
:type lcd_warning: boolean, optional
:returns: dict -- a dict of the analysis
"""
warnings = [] warnings = []
if arch_warning: if arch_warning:
@@ -218,7 +236,7 @@ class Frontend(object):
warnings.append("LengthWarning") warnings.append("LengthWarning")
if lcd_warning: if lcd_warning:
warnings.append("LcdWarning") warnings.append("LCDWarning")
if INSTR_FLAGS.TP_UNKWN in [flag for instr in kernel for flag in instr["flags"]]: if INSTR_FLAGS.TP_UNKWN in [flag for instr in kernel for flag in instr["flags"]]:
warnings.append("UnknownInstrWarning") warnings.append("UnknownInstrWarning")
@@ -231,21 +249,24 @@ class Frontend(object):
if dep_dict: if dep_dict:
longest_lcd = max(dep_dict, key=lambda ln: dep_dict[ln]["latency"]) longest_lcd = max(dep_dict, key=lambda ln: dep_dict[ln]["latency"])
lcd_sum = dep_dict[longest_lcd]["latency"] lcd_sum = dep_dict[longest_lcd]["latency"]
return { return {
"Header": self._header_report_dict(), "Header": self._header_report_dict(),
"Warnings": warnings, "Warnings": warnings,
"Kernel": [ "Kernel": [
{ {
"Line": re.sub(r"\s+", " ", x["line"].strip()), "Line": re.sub(r"\s+", " ", x["line"].strip()),
"LineNumber": x["line_number"],
"Flags": list(x["flags"]), "Flags": list(x["flags"]),
"Instruction": x["instruction"], "Instruction": x["instruction"],
"Operands": AttrDict.get_dict(x["operands"]),
"SemanticOperands": AttrDict.get_dict(x["semantic_operands"]),
"Label": x["label"], "Label": x["label"],
"Latency": x["latency"], "Directive": x["directive"],
"LatencyCP": x["latency_cp"], "Latency": float(x["latency"]),
"LatencyLCD": x["latency_lcd"], "LatencyCP": float(x["latency_cp"]),
"LatencyLCD": float(x["latency_lcd"]),
"Throughput": float(x["throughput"]), "Throughput": float(x["throughput"]),
"LatencyWithoutLoad": x["latency_wo_load"], "LatencyWithoutLoad": float(x["latency_wo_load"]),
"PortPressure": { "PortPressure": {
self._machine_model.get_ports()[i]: v self._machine_model.get_ports()[i]: v
for i, v in enumerate(x["port_pressure"]) for i, v in enumerate(x["port_pressure"])
@@ -257,6 +278,7 @@ class Frontend(object):
} }
for y in x["port_uops"] for y in x["port_uops"]
], ],
"Comment": x["comment"],
} }
for x in kernel for x in kernel
], ],
@@ -526,6 +548,7 @@ class Frontend(object):
return { return {
"Version": _get_version("__init__.py"), "Version": _get_version("__init__.py"),
"FileName": self._filename, "FileName": self._filename,
"Architecture": self._arch,
"Timestamp": dt.utcnow().strftime("%Y-%m-%d %H:%M:%S"), "Timestamp": dt.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
} }

View File

@@ -195,7 +195,7 @@ def create_parser(parser=None):
default=None, default=None,
dest="yaml_out", dest="yaml_out",
type=argparse.FileType("w"), type=argparse.FileType("w"),
help="Write YAML analysis to this file", help="Write analysis as YAML representation to this file",
) )
parser.add_argument( parser.add_argument(
"file", "file",

View File

@@ -27,3 +27,27 @@ class AttrDict(dict):
dictionary[key] = [AttrDict.convert_dict(x) for x in entry] dictionary[key] = [AttrDict.convert_dict(x) for x in entry]
return AttrDict(dictionary) return AttrDict(dictionary)
return dictionary return dictionary
@staticmethod
def get_dict(attrdict):
"""
Convert given `AttrDict` to a standard dictionary.
:param attrdict: `AttrDict` to be converted
:type attrdict: `AttrDict`
:returns: `dict` representation of ``AttrDict``
"""
if isinstance(attrdict, type(list())):
return [AttrDict.get_dict(x) for x in attrdict]
if isinstance(attrdict, type(AttrDict())):
newdict = {}
for key in list(attrdict.keys()):
entry = attrdict[key]
if isinstance(entry, type(dict())) or isinstance(entry, type(AttrDict())):
newdict[key] = AttrDict.get_dict(attrdict[key])
elif isinstance(entry, type(list())):
newdict[key] = [AttrDict.get_dict(x) for x in entry]
else:
newdict[key] = entry
return newdict
return attrdict