diff --git a/tools/ualgui.py b/tools/ualgui.py index d3c153baeae3cdb1938f8bc0ad4f0c7bab8cb2e2..817b2ae0f81fc94a6909fb06f5d2904f75ebde03 100644 --- a/tools/ualgui.py +++ b/tools/ualgui.py @@ -10,27 +10,28 @@ import tkinter.font import tkinter.filedialog import tkinter.ttk as ttk +try: + import cheby.tree + import cheby.parser + import cheby.layout + import cheby.expand_hdl + with_cheby = True +except ImportError as e: + with_cheby = False + import os import re import time import yaml import threading -import subprocess - -from ctypes import * -from ctypes.util import find_library - -import PyUAL +import ualserver +import argparse poll_list_lock = threading.Lock() poll_list = [] -ual = None gual = None tab_view = False - -libc = CDLL(find_library('c')) -getpagesize = libc.getpagesize - +opt_filename = None class Register(tk.Frame): def __init__(self, parent, base_address, reg): @@ -155,9 +156,9 @@ class Register(tk.Frame): print("Read '%s' at address '0x%X'" % (self.register["name"], self.address)) if int(gual.bar.desc.dw.get()) == 2: - value = ual.readw(self.address) + value = my_ual.readw(self.address) elif int(gual.bar.desc.dw.get()) == 4: - value = ual.readl(self.address) + value = my_ual.readl(self.address) value = self.fix_endianess(value) print(" Value = 0x%x" % value) self.print_value(value) @@ -169,9 +170,9 @@ class Register(tk.Frame): value = self.fix_endianess(value) print(" Value = 0x%x" % value) if int(gual.bar.desc.dw.get()) == 2: - value = ual.writew(self.address, value) + value = my_ual.writew(self.address, value) elif int(gual.bar.desc.dw.get()) == 4: - ual.writel(self.address, value) + my_ual.writel(self.address, value) self.get_value() @@ -270,7 +271,6 @@ class MemoryMaps(ttk.Notebook): def __init__(self, parent): self.ranges = {"components": []} self.parent = parent - self.ual = None super(MemoryMaps, self).__init__(self.parent) self.initUI() @@ -320,8 +320,6 @@ class MemoryMaps(ttk.Notebook): """ It adds new components to the current Memory map """ - global ual - if not allow_overlap: for c in self.ranges["components"]: if c["memory"][0] <= group["memory"][0] and \ @@ -333,10 +331,8 @@ class MemoryMaps(ttk.Notebook): print("Add new component %s" % (group)) print(self.ranges) try: - self.mmap = gual.bar.desc.get(self.size(self.ranges["components"])) print("Open UAL") - ual = PyUAL.PyUAL(gual.bar.cmb_bus.get(), self.mmap) - print(ual) + gual.bar.desc.iomap(self.size(self.ranges["components"])) except Exception as e: self.ranges["components"].remove(group) print(e) @@ -466,7 +462,7 @@ class OptionFile(tk.LabelFrame): def initUI(self): self.ent_path = tk.Entry(self, width=15) - self.ent_path.insert(0, os.getcwd()) + self.ent_path.insert(0, default_filename or os.getcwd()) self.ent_path.xview(tk.END) self.ent_path.pack(side=tk.TOP, fill=tk.X, expand=True) @@ -479,6 +475,10 @@ class OptionFile(tk.LabelFrame): command=self.file_load) self.btn_load.pack(side=tk.LEFT, fill=tk.X, expand=True) + if not with_cheby: + self.btn_sel.config(state=tk.DISABLED) + self.btn_load.config(state=tk.DISABLED) + def file_select(self): self.file_opt = options = {} options['defaultextension'] = '.yml' @@ -490,9 +490,26 @@ class OptionFile(tk.LabelFrame): self.ent_path.insert(0, filename) self.ent_path.xview(tk.END) + def cheby_extract_regs(self, t): + res = [] + if isinstance(t, cheby.tree.Reg): + res.append({'name': t.name, 'offset': t.c_address}) + elif isinstance(t, cheby.tree.Array): + pass + elif isinstance(t, cheby.tree.CompositeNode): + for e in t.elements: + res.extend(self.cheby_extract_regs(e)) + return res + def file_load(self): - with open(self.ent_path.get()) as f: - desc = yaml.load(f.read()) + filename = self.ent_path.get() + t = cheby.parser.parse_yaml(filename) + cheby.layout.layout_cheby(t) + cheby.expand_hdl.expand_hdl(t) + regs = self.cheby_extract_regs(t) + desc = {'components': [{'memory': [0, t.c_size], + 'name': t.name, + 'registers': regs}]} gual.mmap.add_descriptor(desc) @@ -556,7 +573,7 @@ class Desc(object): self.lbl_off = tk.Label(self.parent, text="Offset") self.lbl_off.grid(row=2, column=2, sticky="NSWE") - self.offset = tk.Entry(self.parent, width=8) + self.offset = tk.Entry(self.parent, width=10) self.offset.insert(0, "0x0") self.offset.grid(row=2, column=3) @@ -580,17 +597,14 @@ class Desc(object): self.cmb_hend.grid(row=5, column=3) self.cmb_hend.bind("<>", self.change_endianess) - def get(self, size): + def iomap(self, size): pass def change_endianess(self, event): gual.mmap.reload() def bus_list(self): - bus = [] - for b in PyUAL.bus_available(): - bus.append(b) - return bus + return my_ual.get_bus_list() class DescPCI(Desc): @@ -600,8 +614,7 @@ class DescPCI(Desc): def initUI(self): print("Generate PCI GUI") - pci_list = subprocess.check_output("lspci | awk '{print $1}'", - shell=True).split() + pci_list = my_ual.get_pci_list() self.lbl_devid = tk.Label(self.parent, text="Device ID") self.lbl_devid.grid(row=1, column=0, sticky="NSWE") @@ -621,8 +634,7 @@ class DescPCI(Desc): super(DescPCI, self).initUI() self.cmb_dend.set("LE") - def get(self, size): - size = getpagesize() * (int(size / getpagesize()) + 1) + def iomap(self, size): try: offset = int(self.offset.get(), 10) except ValueError: @@ -643,12 +655,7 @@ class DescPCI(Desc): (int(tmp[1], 16) & 0xFF) << 8 | \ (int(tmp[2], 16) & 0xFF) - return PyUAL.PyUALPCI(c_uint64(devid), - c_uint32(dw), - c_uint32(self.bar.get()), - c_uint64(size), - c_uint64(offset), - c_uint64(flags)) + my_ual.iomap_pci(devid, dw, self.bar.get(), size, offset, flags) class DescVME(Desc): @@ -674,8 +681,7 @@ class DescVME(Desc): super(DescVME, self).initUI() self.cmb_dend.set("BE") - def get(self, size): - size = getpagesize() * (int(size / getpagesize()) + 1) + def iomap(self, size): try: offset = int(self.offset.get(), 10) except ValueError: @@ -689,11 +695,7 @@ class DescVME(Desc): flags |= (1 << 0) am = int(self.cmd_am.get(), 16) - return PyUAL.PyUALVME(c_uint32(dw), - c_uint32(am), - c_uint64(size), - c_uint64(offset), - c_uint64(flags)) + my_ual.iomap_vme(dw, am, size, offset, flags) class BaseAddressRegister(tk.LabelFrame): @@ -735,10 +737,7 @@ class BaseAddressRegister(tk.LabelFrame): self.event_generate("<>") def bus_list(self): - bus = [] - for b in PyUAL.bus_available(): - bus.append(b) - return bus + return my_ual.get_bus_list() def enable(self, value): st = "readonly" if value else tk.DISABLED @@ -776,15 +775,18 @@ class GuiUal(tk.Frame): self.mmap.pack(side=tk.LEFT, fill=tk.X, anchor="n") def bus_changed(self, event): - global ual + my_ual.unmap() # Destory all MemoryMaps contents for w in self.mmap.winfo_children(): w.destroy() - ual = None - if __name__ == "__main__": + parser = argparse.ArgumentParser(description='GUI for io access') + parser.add_argument('-r', '--remote', help='url of the remote server') + parser.add_argument('-f', '--filename', help='specify default filename') + + args = parser.parse_args() root = tk.Tk() try: default_font = tk.font.nametofont("TkDefaultFont") @@ -792,6 +794,13 @@ if __name__ == "__main__": except tkinter.TclError: print('failed to set up default fonts, continuing') + default_filename = args.filename + + if args.remote is None: + my_ual = ualserver.UALLocal() + else: + my_ual = ualserver.UALRemote(args.remote) + gual = GuiUal(root) gual.pack(fill=tk.BOTH, expand=True) root.mainloop() diff --git a/tools/ualserver.py b/tools/ualserver.py new file mode 100755 index 0000000000000000000000000000000000000000..5021aa102f13f154fdaaca7ec31f85dc777a4fb6 --- /dev/null +++ b/tools/ualserver.py @@ -0,0 +1,141 @@ +import subprocess +import ctypes +from ctypes.util import find_library + +class UALBase(object): + def get_bus_list(self): + raise NotImplemented + + def get_pci_list(self): + raise NotImplemented + + def iomap_pci(self, devid, dw, bar, size, offset, flags): + raise NotImplemented + + def iomap_vme(self, dw, am, size, offset, flags): + raise NotImplemented + + def iomap(self): + raise NotImplemented + + def unmap(self): + raise NotImplemented + + def readl(self, off): + raise NotImplemented + + def readw(self, off): + raise NotImplemented + + def writel(self, off, val): + raise NotImplemented + + def writew(self, off, val): + raise NotImplemented + + +class UALLocal(UALBase): + def __init__(self): + import PyUAL + self.PyUAL = PyUAL + + libc = ctypes.CDLL(find_library('c')) + self.pagesize = libc.getpagesize() + + def get_bus_list(self): + return [b for b in self.PyUAL.bus_available()] + + def get_pci_list(self): + pci_list = subprocess.check_output("lspci | awk '{print $1}'", + shell=True).split() + return pci_list + + def iomap_vme(self, dw, am, size, offset, flags): + size = (size + self.pagesize - 1) & ~(self.pagesize - 1) + desc = self.PyUAL.PyUALVME(ctypes.c_uint32(dw), + ctypes.c_uint32(am), + ctypes.c_uint64(size), + ctypes.c_uint64(offset), + ctypes.c_uint64(flags)) + self.ual = self.PyUAL.PyUAL('vme', desc) + + def iomap_pci(self, devid, dw, bar, size, offset, flags): + size = (size + self.pagesize - 1) & ~(self.pagesize - 1) + desc = self.PyUAL.PyUALPCI(ctypes.c_uint64(devid), + ctypes.c_uint32(dw), + ctypes.c_uint32(bar), + ctypes.c_uint64(size), + ctypes.c_uint64(offset), + ctypes.c_uint64(flags)) + self.ual = self.PyUAL.PyUAL('pci', desc) + + def unmap(self): + self.ual = None + + def readl(self, off): + return self.ual.readl(off) + + def readw(self, off): + return self.ual.readw(off) + + def writel(self, off, val): + self.ual.writel(off, val) + + def writew(self, off, val): + self.ual.writew(off, val) + + +class UALRemote(UALBase): + def __init__(self, uri): + import xmlrpc.client + self.client = xmlrpc.client.ServerProxy(uri) + + def get_bus_list(self): + return self.client.get_bus_list() + + def get_pci_list(self): + return self.client.get_pci_list() + + def iomap_vme(self, dw, am, size, offset, flags): + self.client.iomap_vme(dw, am, size, offset, flags) + + def iomap_pci(self, devid, dw, bar, size, offset, flags): + self.client.iomap_pci(devid, dw, bar, size, offset, flags) + + def unmap(self): + self.client.unmap() + + def readl(self, off): + return self.client.readl(off) + + def readw(self, off): + return self.client.readw(off) + + def writel(self, off, val): + self.client.writel(off, val) + + def writew(self, off, val): + self.client.writew(off, val) + + +if __name__ == "__main__": + import xmlrpc.server + import argparse + + parser = argparse.ArgumentParser(description='UAL remote server') + parser.add_argument('-p', '--port', type=int, default=8000, + help='local TCP port') + parser.add_argument('--log', action='store_true', default=False, + help='enable log') + # parser.add_argument('-r', '--remote', help='url of the remote server') + + args = parser.parse_args() + + server = xmlrpc.server.SimpleXMLRPCServer( + ("", args.port), logRequests=args.log, allow_none=True) + + my_ual = UALLocal() + server.register_instance(my_ual) + + print("Listening on port {}...".format(args.port)) + server.serve_forever()