From d781f80c9b3e0e48b36ac5b5bca760d0f52468a8 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Mon, 15 May 2023 20:18:45 +0000 Subject: [PATCH] cyclemodel/inorder.py: implement basic trace parsing --- src/openpower/cyclemodel/inorder.py | 115 ++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/src/openpower/cyclemodel/inorder.py b/src/openpower/cyclemodel/inorder.py index 8dad20b8..bcff6956 100644 --- a/src/openpower/cyclemodel/inorder.py +++ b/src/openpower/cyclemodel/inorder.py @@ -15,6 +15,106 @@ """ +import dataclasses as _dataclasses +import enum as _enum +import re as _re + + +class Action(_enum.Enum): + READ = "r" + WRITE = "w" + + def __str__(self): + return self.value + + +class Target(_enum.Enum): + GPR = "GPR" + FPR = "FPR" + CR = "CR" + CRf = "CRf" + XER = "XER" + MSR = "MSR" + FPSCR = "FPSCR" + SPRf = "SPRf" + SPRs = "SPRs" + + def __str__(self): + return self.value + + +class Ident(int): + pass + + +class Offset(int): + pass + + +class Width(int): + pass + + +PATTERN_ACTION = "|".join(map(str, Action)) +PATTERN_TARGET = "|".join(map(str, Target)) +PATTERN_IDENT = r"[0-9]+" +PATTERN_OFFSET = r"[0-9]+" +PATTERN_WIDTH = r"[0-9]+" + +# {ACTION}{TARGET}:{IDENT}.{OFFSET}/{WIDTH} +PATTERN = "".join(( + "^", + rf"(?P{PATTERN_ACTION})", + rf"(?P{PATTERN_TARGET})", + r":", + rf"(?P{PATTERN_IDENT})", + r"\.", + rf"(?P{PATTERN_OFFSET})", + r"\/", + rf"(?P{PATTERN_WIDTH})", + "$", +)) +REGEX = _re.compile(PATTERN, _re.M) + + +@_dataclasses.dataclass(frozen=True, eq=True) +class Trace: + action: Action + target: Target + ident: Ident + offset: Offset + width: Width + + def __str__(self): + return "".join(map(str, ( + self.action, + self.target, + ":", + self.ident, + ".", + self.offset, + "/", + self.width, + ))) + + @classmethod + def parse(cls, string): + origin = string + if not isinstance(origin, str): + raise ValueError(origin) + + (string, _, _) = map(str.strip, string.partition(" # ")) + if not string: + raise ValueError(origin) + + fields = {field.name:field.type for field in _dataclasses.fields(cls)} + for part in _re.split(r"\s", string.strip()): + match = REGEX.match(part) + if match is None: + raise ValueError(origin) + match = match.groupdict().items() + return cls(**{key:fields[key](value) for (key, value) in match}) + class RegisterWrite: """ @@ -200,3 +300,18 @@ class CPU: self.decode.tick() self.issue.tick() self.exe.tick() + + +if __name__ == "__main__": + lines = ( + "rGPR:0.0/64 wGPR:1.0/64 # addi 1, 0, 0x0010", + "rGPR:0.0/64 wGPR:2.0/64 # addi 2, 0, 0x1234", + "rGPR:1.0/64 rGPR:2.0/64 # stw 2, 0(1)", + "rGPR:1.0/64 wGPR:3.0/64 # lwz 3, 0(1)", + "rGPR:3.0/64 rGPR:2.0/64 wGPR:1.0/64 # add 1, 3, 2", + "rGPR:0.0/64 wGPR:3.0/64 # addi 3, 0, 0x1234", + "rGPR:0.0/64 wGPR:2.0/64 # addi 2, 0, 0x4321", + "rGPR:3.0/64 rGPR:2.0/64 wGPR:1.0/64 # add 1, 3, 2", + ) + for trace in map(Trace.parse, lines): + print(trace) -- 2.30.2