summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/trace/asc.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/proxyclient/m1n1/trace/asc.py')
-rw-r--r--tools/proxyclient/m1n1/trace/asc.py271
1 files changed, 271 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/trace/asc.py b/tools/proxyclient/m1n1/trace/asc.py
new file mode 100644
index 0000000..6d63a50
--- /dev/null
+++ b/tools/proxyclient/m1n1/trace/asc.py
@@ -0,0 +1,271 @@
+# SPDX-License-Identifier: MIT
+
+import struct
+from enum import IntEnum
+from ..hv import TraceMode
+from ..utils import *
+from . import ADTDevTracer
+from ..hw.asc import *
+
+class DIR(IntEnum):
+ RX = 0
+ TX = 1
+
+def msg(message, direction=None, regtype=None, name=None):
+ def f(x):
+ x.is_message = True
+ x.direction = direction
+ x.message = message
+ x.regtype = regtype
+ x.name = name
+ return x
+ return f
+
+def msg_log(*args, **kwargs):
+ def x(self, msg):
+ return False
+ return msg(*args, **kwargs)(x)
+
+def msg_ign(*args, **kwargs):
+ def x(self, msg):
+ return True
+ return msg(*args, **kwargs)(x)
+
+class EPState(object):
+ pass
+
+class EP(object):
+ NAME = None
+ BASE_MESSAGE = None
+
+ def __init__(self, tracer, epid):
+ self.tracer = tracer
+ self.epid = epid
+ self.present = False
+ self.started = False
+ self.name = self.NAME or type(self).__name__.lower()
+ self.state = EPState()
+ self.hv = self.tracer.hv
+ self.msgmap = {}
+ for name in dir(self):
+ i = getattr(self, name)
+ if not callable(i) or not getattr(i, "is_message", False):
+ continue
+ self.msgmap[i.direction, i.message] = getattr(self, name), name, i.regtype
+
+ def log(self, msg):
+ self.tracer.log(f"[{self.name}] {msg}")
+
+ def start(self):
+ pass
+
+ def handle_msg(self, direction, r0, r1):
+ msgtype = None
+ if self.BASE_MESSAGE:
+ r0 = self.BASE_MESSAGE(r0.value)
+ msgtype = r0.TYPE
+
+ handler = None
+ name = "<unknown>"
+ regtype = None
+
+ msgids = [
+ (direction, msgtype),
+ (None, msgtype),
+ (direction, None),
+ (None, None),
+ ]
+
+ for msgid in msgids:
+ handler, name, regtype = self.msgmap.get(msgid, (None, None, None))
+ if handler:
+ break
+
+ if regtype is not None:
+ r0 = regtype(r0.value)
+
+ if handler:
+ if handler.name is not None:
+ name = handler.name
+ if handler(r0):
+ return True
+
+ d = ">" if direction == DIR.TX else "<"
+ self.log(f"{d}{msgtype:#x}({name}) {r0.value:016x} ({r0.str_fields()})")
+ return True
+
+class EPContainer(object):
+ pass
+
+class BaseASCTracer(ADTDevTracer):
+ DEFAULT_MODE = TraceMode.SYNC
+
+ REGMAPS = [ASCRegs, None]
+ NAMES = ["asc", None]
+
+ ENDPOINTS = {}
+
+ def w_OUTBOX_CTRL(self, val):
+ self.log(f"OUTBOX_CTRL = {val!s}")
+
+ def w_INBOX_CTRL(self, val):
+ self.log(f"INBOX_CTRL = {val!s}")
+
+ def w_CPU_CONTROL(self, val):
+ self.log(f"CPU_CONTROL = {val!s}")
+
+ def w_INBOX1(self, inbox1):
+ inbox0 = self.asc.cached.INBOX0.reg
+ if self.verbose >= 2:
+ self.log(f"SEND: {inbox0.value:016x}:{inbox1.value:016x} " +
+ f"{inbox0.str_fields()} | {inbox1.str_fields()}")
+ self.handle_msg(DIR.TX, inbox0, inbox1)
+
+ def r_OUTBOX1(self, outbox1):
+ outbox0 = self.asc.cached.OUTBOX0.reg
+ if self.verbose >= 2:
+ self.log(f"RECV: {outbox0.value:016x}:{outbox1.value:016x} " +
+ f"{outbox0.str_fields()} | {outbox1.str_fields()}")
+ self.handle_msg(DIR.RX, outbox0, outbox1)
+
+ def init_state(self):
+ self.state.ep = {}
+
+ def handle_msg(self, direction, r0, r1):
+ if r1.EP in self.epmap:
+ if self.epmap[r1.EP].handle_msg(direction, r0, r1):
+ return
+
+ d = ">" if direction == DIR.TX else "<"
+ self.log(f"{d}ep:{r1.EP:02x} {r0.value:016x} ({r0.str_fields()})")
+
+ def ioread(self, dva, size):
+ if self.dart:
+ return self.dart.ioread(self.stream, dva & 0xFFFFFFFFF, size)
+ else:
+ return self.hv.iface.readmem(dva, size)
+
+ def iowrite(self, dva, data):
+ if self.dart:
+ return self.dart.iowrite(self.stream, dva & 0xFFFFFFFFF, data)
+ else:
+ return self.hv.iface.writemem(dva, data)
+
+ def start(self, dart=None, stream=0):
+ super().start()
+ self.dart = dart
+ self.stream = stream
+ self.msgmap = {}
+ for name in dir(self):
+ i = getattr(self, name)
+ if not callable(i) or not getattr(i, "is_message", False):
+ continue
+ self.msgmap[i.direction, i.endpoint, i.message] = getattr(self, name), name, i.regtype
+
+ self.epmap = {}
+ self.ep = EPContainer()
+ for cls in type(self).mro():
+ eps = getattr(cls, "ENDPOINTS", None)
+ if eps is None:
+ break
+ for k, v in eps.items():
+ if k in self.epmap:
+ continue
+ ep = v(self, k)
+ ep.dart = dart
+ ep.stream = stream
+ self.epmap[k] = ep
+ if k in self.state.ep:
+ ep.state.__dict__.update(self.state.ep[k])
+ self.state.ep[k] = ep.state.__dict__
+ if getattr(self.ep, ep.name, None):
+ ep.name = f"{ep.name}{k:02x}"
+ setattr(self.ep, ep.name, ep)
+ ep.start()
+
+# System endpoints
+
+## Management endpoint
+
+from ..fw.asc.mgmt import ManagementMessage, Mgmt_EPMap, Mgmt_EPMap_Ack, Mgmt_StartEP, Mgmt_SetAPPower, Mgmt_SetIOPPower, Mgmt_IOPPowerAck
+
+class Management(EP):
+ BASE_MESSAGE = ManagementMessage
+
+ HELLO = msg_log(1, DIR.RX)
+ HELLO_ACK = msg_log(2, DIR.TX)
+
+ @msg(5, DIR.TX, Mgmt_StartEP)
+ def StartEP(self, msg):
+ ep = self.tracer.epmap.get(msg.EP, None)
+ if ep:
+ ep.started = True
+ self.log(f" Starting endpoint #{msg.EP:#02x} ({ep.name})")
+ else:
+ self.log(f" Starting endpoint #{msg.EP:#02x}")
+ #return True
+
+ Init = msg_log(6, DIR.TX)
+
+ @msg(8, DIR.RX, Mgmt_EPMap)
+ def EPMap(self, msg):
+ for i in range(32):
+ if msg.BITMAP & (1 << i):
+ epno = 32 * msg.BASE + i
+ ep = self.tracer.epmap.get(epno, None)
+ if ep:
+ ep.present = True
+ self.log(f" Adding endpoint #{epno:#02x} ({ep.name})")
+ else:
+ self.log(f" Adding endpoint #{epno:#02x}")
+
+ EPMap_Ack = msg_log(8, DIR.TX, Mgmt_EPMap_Ack)
+
+ SetIOPPower = msg_log(6, DIR.TX, Mgmt_SetIOPPower)
+ SetIOPPowerAck = msg_log(7, DIR.TX, Mgmt_IOPPowerAck)
+
+ SetAPPower = msg_log(0x0b, DIR.TX, Mgmt_SetAPPower)
+ SetAPPowerAck = msg_log(0x0b, DIR.RX, Mgmt_SetAPPower)
+
+## Syslog endpoint
+
+from ..fw.asc.syslog import SyslogMessage, Syslog_Init, Syslog_GetBuf, Syslog_Log
+
+class Syslog(EP):
+ BASE_MESSAGE = SyslogMessage
+
+ @msg(8, DIR.RX, Syslog_Init)
+ def Init(self, msg):
+ self.state.count = msg.COUNT
+ self.state.entrysize = msg.ENTRYSIZE
+
+ @msg(1, DIR.RX, Syslog_GetBuf)
+ def GetBuf(self, msg):
+ if msg.DVA:
+ self.state.syslog_buf = msg.DVA
+
+ @msg(1, DIR.TX, Syslog_GetBuf)
+ def GetBuf_Ack(self, msg):
+ self.state.syslog_buf = msg.DVA
+
+ @msg(5, DIR.RX, Syslog_Log)
+ def Log(self, msg):
+ buf = self.state.syslog_buf
+ stride = 0x20 + self.state.entrysize
+ log = self.tracer.ioread(buf + msg.INDEX * stride, stride)
+ hdr, unk, context, logmsg = struct.unpack(f"<II24s{self.state.entrysize}s", log)
+ context = context.split(b"\x00")[0].decode("ascii")
+ logmsg = logmsg.split(b"\x00")[0].decode("ascii").rstrip("\n")
+ self.log(f"* [{context}]{logmsg}")
+ return True
+
+ Log_Ack = msg_ign(5, DIR.TX, Syslog_Log)
+
+class ASCTracer(BaseASCTracer):
+ ENDPOINTS = {
+ 0: Management,
+ #1: CrashLog,
+ 2: Syslog,
+ #3: KDebug,
+ #4: IOReporting,
+ }