mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-14 19:27:06 +00:00
m1n1.gpiola: New module
Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
5e202ab2fe
commit
a05f68d1c8
1 changed files with 201 additions and 0 deletions
201
proxyclient/m1n1/gpiola.py
Normal file
201
proxyclient/m1n1/gpiola.py
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
import os, sys, struct, time
|
||||||
|
|
||||||
|
from .utils import *
|
||||||
|
from . import asm
|
||||||
|
from .proxy import REGION_RX_EL1
|
||||||
|
from .sysreg import *
|
||||||
|
|
||||||
|
class GPIOLogicAnalyzer(object):
|
||||||
|
def __init__(self, u, node, pins, regs=[], div=1, cpu=1, on_pin_change=True):
|
||||||
|
self.u = u
|
||||||
|
self.p = u.proxy
|
||||||
|
self.iface = u.iface
|
||||||
|
self.cpu = cpu
|
||||||
|
self.base = u.adt[node].get_reg(0)[0]
|
||||||
|
self.node = node
|
||||||
|
self.pins = pins
|
||||||
|
self.regs = regs
|
||||||
|
assert len(pins) <= 32
|
||||||
|
assert div > 0
|
||||||
|
self.div = div
|
||||||
|
self.cbuf = self.u.malloc(0x1000)
|
||||||
|
self.dbuf = None
|
||||||
|
self.on_pin_change = on_pin_change
|
||||||
|
self.p.mmu_init_secondary(cpu)
|
||||||
|
self.tfreq = u.mrs(CNTFRQ_EL0)
|
||||||
|
|
||||||
|
def start(self, ticks, bufsize=0x10000):
|
||||||
|
self.bufsize = bufsize
|
||||||
|
if self.dbuf:
|
||||||
|
self.u.free(self.dbuf)
|
||||||
|
self.dbuf = self.u.malloc(bufsize)
|
||||||
|
|
||||||
|
text = f"""
|
||||||
|
trace:
|
||||||
|
add x3, x3, x2
|
||||||
|
mov x10, x2
|
||||||
|
mov x6, #-1
|
||||||
|
mov x7, #0
|
||||||
|
ldr x8, ={self.base}
|
||||||
|
mrs x4, CNTPCT_EL0
|
||||||
|
isb
|
||||||
|
1:
|
||||||
|
add x4, x4, x1
|
||||||
|
2:
|
||||||
|
mrs x5, CNTPCT_EL0
|
||||||
|
isb
|
||||||
|
cmp x5, x4
|
||||||
|
b.lo 2b
|
||||||
|
"""
|
||||||
|
|
||||||
|
for idx, pin in enumerate(self.pins.values()):
|
||||||
|
text += f"""
|
||||||
|
ldr w9, [x8, #{pin * 4}]
|
||||||
|
bfi x7, x9, #{idx}, #1
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.on_pin_change:
|
||||||
|
text += f"""
|
||||||
|
cmp x7, x6
|
||||||
|
b.eq 3f
|
||||||
|
mov x6, x7
|
||||||
|
"""
|
||||||
|
text += f"""
|
||||||
|
str w5, [x2], #4
|
||||||
|
str w7, [x2], #4
|
||||||
|
"""
|
||||||
|
|
||||||
|
for reg in self.regs.values():
|
||||||
|
if isinstance(reg, tuple):
|
||||||
|
reg = reg[0]
|
||||||
|
text += f"""
|
||||||
|
ldr x9, ={reg}
|
||||||
|
ldr w9, [x9]
|
||||||
|
str w9, [x2], #4
|
||||||
|
"""
|
||||||
|
|
||||||
|
text += f"""
|
||||||
|
cmp x2, x3
|
||||||
|
b.hs 2f
|
||||||
|
3:
|
||||||
|
sub x0, x0, #1
|
||||||
|
cbnz x0, 1b
|
||||||
|
2:
|
||||||
|
sub x0, x2, x10
|
||||||
|
ret
|
||||||
|
"""
|
||||||
|
|
||||||
|
code = asm.ARMAsm(text, self.cbuf)
|
||||||
|
self.iface.writemem(self.cbuf, code.data)
|
||||||
|
self.p.dc_cvau(self.cbuf, len(code.data))
|
||||||
|
self.p.ic_ivau(self.cbuf, len(code.data))
|
||||||
|
|
||||||
|
self.p.smp_call(self.cpu, code.trace | REGION_RX_EL1, ticks, self.div, self.dbuf, bufsize - (8 + 4 * len(self.regs)))
|
||||||
|
|
||||||
|
def complete(self):
|
||||||
|
wrote = self.p.smp_wait(self.cpu)
|
||||||
|
assert wrote <= self.bufsize
|
||||||
|
data = self.iface.readmem(self.dbuf, wrote)
|
||||||
|
self.u.free(self.dbuf)
|
||||||
|
self.dbuf = None
|
||||||
|
|
||||||
|
stride = 2 + len(self.regs)
|
||||||
|
|
||||||
|
#chexdump(data)
|
||||||
|
|
||||||
|
self.data = [struct.unpack("<" + "I" * stride,
|
||||||
|
data[i:i + 4 * stride])
|
||||||
|
for i in range(0, len(data), 4 * stride)]
|
||||||
|
|
||||||
|
def vcd(self):
|
||||||
|
off = self.data[0][0]
|
||||||
|
if len(self.data) > 1:
|
||||||
|
off2 = max(0, ((self.data[1][0] - off) & 0xffffffff) - 5000)
|
||||||
|
else:
|
||||||
|
off2 = 0
|
||||||
|
|
||||||
|
print(off, off2)
|
||||||
|
|
||||||
|
vcd = []
|
||||||
|
vcd.append("""
|
||||||
|
$timescale 1ns $end
|
||||||
|
$scope module gpio $end
|
||||||
|
""")
|
||||||
|
sym = 0
|
||||||
|
keys = []
|
||||||
|
rkeys = []
|
||||||
|
|
||||||
|
for name in self.pins:
|
||||||
|
keys.append(f"s{sym}")
|
||||||
|
vcd.append(f"$var wire 1 s{sym} {name} $end\n")
|
||||||
|
sym += 1
|
||||||
|
for name, reg in self.regs.items():
|
||||||
|
vcd.append(f"$var reg 32 s{sym} {name} [31:0] $end\n")
|
||||||
|
if isinstance(reg, tuple):
|
||||||
|
subkeys = {}
|
||||||
|
rcls = reg[1]
|
||||||
|
rkeys.append((f"s{sym}", rcls, subkeys))
|
||||||
|
sym += 1
|
||||||
|
for fname in rcls().fields.keys():
|
||||||
|
fdef = getattr(rcls, fname)
|
||||||
|
if isinstance(fdef, tuple):
|
||||||
|
width = fdef[0] - fdef[1] + 1
|
||||||
|
else:
|
||||||
|
width = 1
|
||||||
|
vcd.append(f"$var reg {width} s{sym} {name}.{fname} [{width-1}:0] $end\n")
|
||||||
|
subkeys[fname] = (width, f"s{sym}")
|
||||||
|
sym += 1
|
||||||
|
else:
|
||||||
|
rkeys.append((f"s{sym}", None, None))
|
||||||
|
sym += 1
|
||||||
|
vcd.append("""
|
||||||
|
$enddefinitions $end
|
||||||
|
$dumpvars
|
||||||
|
""")
|
||||||
|
|
||||||
|
for v in self.data:
|
||||||
|
ts = v[0]
|
||||||
|
val = v[1]
|
||||||
|
regs = v[2:]
|
||||||
|
ts = ((ts - off) & 0xffffffff) - off2
|
||||||
|
ns = max(0, 1000000000 * ts // self.tfreq)
|
||||||
|
vcd.append(f"#{ns}\n")
|
||||||
|
vcd.append("\n".join(f"{(val>>i) & 1}{k}" for i, k in enumerate(keys)) + "\n")
|
||||||
|
for (key, rcls, subkeys), v in zip(rkeys, regs):
|
||||||
|
vcd.append(f"b{v:032b} {key}\n")
|
||||||
|
if rcls:
|
||||||
|
rval = rcls(v)
|
||||||
|
for field, (width, key) in subkeys.items():
|
||||||
|
v = getattr(rval, field)
|
||||||
|
vcd.append(f"b{v:0{width}b} {key}\n")
|
||||||
|
|
||||||
|
|
||||||
|
ns += 10000
|
||||||
|
vcd.append(f"#{ns}\n" + "\n".join(f"{(val>>i) & 1}{k}" for i, k in enumerate(keys)) + "\n")
|
||||||
|
|
||||||
|
return "".join(vcd)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
with open("/tmp/dump.vcd", "w") as fd:
|
||||||
|
fd.write(self.vcd())
|
||||||
|
|
||||||
|
gtkw = ("""
|
||||||
|
[dumpfile] "/tmp/dump.vcd"
|
||||||
|
[timestart] 0
|
||||||
|
[size] 3063 1418
|
||||||
|
[pos] -1 -1
|
||||||
|
*-17.000000 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||||
|
[sst_width] 288
|
||||||
|
[signals_width] 197
|
||||||
|
[sst_expanded] 1
|
||||||
|
[sst_vpaned_height] 421
|
||||||
|
@23
|
||||||
|
""" +
|
||||||
|
"\n".join("gpio." + k for k in self.pins) + "\n" +
|
||||||
|
"\n".join("gpio." + k + "[31:0]" for k in self.regs) + "\n")
|
||||||
|
|
||||||
|
with open("/tmp/dump.gtkw", "w") as fd:
|
||||||
|
fd.write(gtkw)
|
||||||
|
|
||||||
|
os.system("gtkwave /tmp/dump.gtkw")
|
Loading…
Reference in a new issue