cyclemodel/inorder.py: implement basic trace parsing tracefile
authorDmitry Selyutin <ghostmansd@gmail.com>
Mon, 15 May 2023 20:18:45 +0000 (20:18 +0000)
committerDmitry Selyutin <ghostmansd@gmail.com>
Mon, 15 May 2023 20:18:45 +0000 (20:18 +0000)
src/openpower/cyclemodel/inorder.py

index 8dad20b8a87d652d50e93069f5b431d386ed8bf4..bcff6956685af1a8f5f43e8f8074112f71f60306 100644 (file)
 
 """
 
+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<action>{PATTERN_ACTION})",
+    rf"(?P<target>{PATTERN_TARGET})",
+    r":",
+    rf"(?P<ident>{PATTERN_IDENT})",
+    r"\.",
+    rf"(?P<offset>{PATTERN_OFFSET})",
+    r"\/",
+    rf"(?P<width>{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)