diff --git a/osaca/frontend.py b/osaca/frontend.py index 06b55e7..9a5521d 100755 --- a/osaca/frontend.py +++ b/osaca/frontend.py @@ -8,6 +8,7 @@ import re from datetime import datetime as dt from osaca.semantics import INSTR_FLAGS, ArchSemantics, KernelDG, MachineModel +from osaca.parser import AttrDict def _get_version(*file_paths): @@ -209,6 +210,23 @@ class Frontend(object): length_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 = [] if arch_warning: @@ -218,7 +236,7 @@ class Frontend(object): warnings.append("LengthWarning") 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"]]: warnings.append("UnknownInstrWarning") @@ -231,21 +249,24 @@ class Frontend(object): if dep_dict: longest_lcd = max(dep_dict, key=lambda ln: dep_dict[ln]["latency"]) lcd_sum = dep_dict[longest_lcd]["latency"] - return { "Header": self._header_report_dict(), "Warnings": warnings, "Kernel": [ { "Line": re.sub(r"\s+", " ", x["line"].strip()), + "LineNumber": x["line_number"], "Flags": list(x["flags"]), "Instruction": x["instruction"], + "Operands": AttrDict.get_dict(x["operands"]), + "SemanticOperands": AttrDict.get_dict(x["semantic_operands"]), "Label": x["label"], - "Latency": x["latency"], - "LatencyCP": x["latency_cp"], - "LatencyLCD": x["latency_lcd"], + "Directive": x["directive"], + "Latency": float(x["latency"]), + "LatencyCP": float(x["latency_cp"]), + "LatencyLCD": float(x["latency_lcd"]), "Throughput": float(x["throughput"]), - "LatencyWithoutLoad": x["latency_wo_load"], + "LatencyWithoutLoad": float(x["latency_wo_load"]), "PortPressure": { self._machine_model.get_ports()[i]: v for i, v in enumerate(x["port_pressure"]) @@ -257,6 +278,7 @@ class Frontend(object): } for y in x["port_uops"] ], + "Comment": x["comment"], } for x in kernel ], @@ -526,6 +548,7 @@ class Frontend(object): return { "Version": _get_version("__init__.py"), "FileName": self._filename, + "Architecture": self._arch, "Timestamp": dt.utcnow().strftime("%Y-%m-%d %H:%M:%S"), } diff --git a/osaca/osaca.py b/osaca/osaca.py index a6e57e9..51d46b6 100755 --- a/osaca/osaca.py +++ b/osaca/osaca.py @@ -195,7 +195,7 @@ def create_parser(parser=None): default=None, dest="yaml_out", type=argparse.FileType("w"), - help="Write YAML analysis to this file", + help="Write analysis as YAML representation to this file", ) parser.add_argument( "file", diff --git a/osaca/parser/attr_dict.py b/osaca/parser/attr_dict.py index 6348599..35f6c40 100755 --- a/osaca/parser/attr_dict.py +++ b/osaca/parser/attr_dict.py @@ -27,3 +27,27 @@ class AttrDict(dict): dictionary[key] = [AttrDict.convert_dict(x) for x in entry] return AttrDict(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