forked from M-Labs/artiq
1
0
Fork 0

Compare commits

...

10 Commits

13 changed files with 124 additions and 177 deletions

View File

@ -29,7 +29,7 @@ Website: https://m-labs.hk/artiq
License
=======
Copyright (C) 2014-2023 M-Labs Limited.
Copyright (C) 2014-2024 M-Labs Limited.
ARTIQ is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by

View File

@ -369,6 +369,8 @@ class ExperimentsArea(QtWidgets.QMdiArea):
def initialize_submission_arguments(self, arginfo):
arguments = OrderedDict()
for name, (procdesc, group, tooltip) in arginfo.items():
if procdesc["ty"] == "EnumerationValue" and procdesc["quickstyle"]:
procdesc["quickstyle"] = False
state = procdesc_to_entry(procdesc).default_state(procdesc)
arguments[name] = {
"desc": procdesc,

View File

@ -999,7 +999,7 @@ class AD9910:
"""
if not self.cpld.sync_div:
raise ValueError("parent cpld does not drive SYNC")
search_span = 31
search_span = 13
# FIXME https://github.com/sinara-hw/Urukul/issues/16
# should both be 2-4 once kasli sync_in jitter is identified
min_window = 0

View File

@ -94,7 +94,7 @@ class _OpenFileDialog(QtWidgets.QDialog):
else:
break
self.explorer.current_directory = \
self.explorer.current_directory[:idx+1]
self.explorer.current_directory[:idx + 1]
if self.explorer.current_directory == "/":
self.explorer.current_directory = ""
asyncio.ensure_future(self.refresh_view())
@ -103,6 +103,7 @@ class _OpenFileDialog(QtWidgets.QDialog):
asyncio.ensure_future(self.refresh_view())
else:
file = self.explorer.current_directory + selected
async def open_task():
try:
await self.exp_manager.open_file(file)
@ -232,7 +233,7 @@ class ExplorerDock(QtWidgets.QDockWidget):
set_shortcut_menu = QtWidgets.QMenu()
for i in range(12):
action = QtWidgets.QAction("F" + str(i+1), self.el)
action = QtWidgets.QAction("F" + str(i + 1), self.el)
action.triggered.connect(partial(self.set_shortcut, i))
set_shortcut_menu.addAction(action)
@ -246,12 +247,14 @@ class ExplorerDock(QtWidgets.QDockWidget):
scan_repository_action = QtWidgets.QAction("Scan repository HEAD",
self.el)
def scan_repository():
asyncio.ensure_future(experiment_db_ctl.scan_repository_async())
scan_repository_action.triggered.connect(scan_repository)
self.el.addAction(scan_repository_action)
scan_ddb_action = QtWidgets.QAction("Scan device database", self.el)
def scan_ddb():
asyncio.ensure_future(device_db_ctl.scan())
scan_ddb_action.triggered.connect(scan_ddb)
@ -292,7 +295,7 @@ class ExplorerDock(QtWidgets.QDockWidget):
if expname is not None:
expurl = "repo:" + expname
self.d_shortcuts.set_shortcut(nr, expurl)
logger.info("Set shortcut F%d to '%s'", nr+1, expurl)
logger.info("Set shortcut F%d to '%s'", nr + 1, expurl)
def update_scanning(self, scanning):
if scanning:

View File

@ -363,61 +363,72 @@ class _DACWidget(_SimpleDisplayWidget):
return (self.spi_channel, self.channel)
_WidgetDesc = namedtuple("_WidgetDesc", "uid comment cls arguments")
_ChannelDesc = namedtuple("_ChannelDesc", "name widget_type clss kwargs")
def _setup_ttl(k, v, description):
if "ttl_urukul" in k:
return
channel = v["arguments"]["channel"]
channel_desc = _ChannelDesc(k, _TTLWidget, v["class"], {})
description[(channel, None)] = channel_desc
def _setup_ad9914(k, v, description):
bus_channel = v["arguments"]["bus_channel"]
channel = v["arguments"]["channel"]
dds_sysclk = v["arguments"]["sysclk"]
channel_desc = _ChannelDesc(k, _DDSWidget, v["class"],
{"dds_sysclk": dds_sysclk})
description[(bus_channel, channel)] = channel_desc
def _setup_urukul(k, v, description, ddb):
channel = v["arguments"]["chip_select"] - 4
if channel < 0:
return
dds_cpld = v["arguments"]["cpld_device"]
spi_dev = ddb[dds_cpld]["arguments"]["spi_device"]
bus_channel = ddb[spi_dev]["arguments"]["channel"]
pll = v["arguments"]["pll_n"]
refclk = ddb[dds_cpld]["arguments"]["refclk"]
clk_div = v["arguments"].get("clk_div", 0)
channel_desc = _ChannelDesc(k, _DDSWidget, v["class"],
{"refclk": refclk, "dds_cpld": dds_cpld,
"pll": pll, "clk_div": clk_div})
description[(bus_channel, channel)] = channel_desc
def _setup_dac(k, v, description, ddb):
spi_device = v["arguments"]["spi_device"]
spi_device = ddb[spi_device]
while isinstance(spi_device, str):
spi_device = ddb[spi_device]
spi_channel = spi_device["arguments"]["channel"]
for channel in range(32):
channel_desc = _ChannelDesc(k, _DACWidget, v["class"], {})
description[(spi_channel, channel)] = channel_desc
def setup_from_ddb(ddb):
mi_addr = None
mi_port = None
dds_sysclk = None
description = set()
description = dict() # (uid, channel) -> _ChannelDesc
for k, v in ddb.items():
try:
if isinstance(v, dict):
comment = v.get("comment")
if v["type"] == "local":
if v["module"] == "artiq.coredevice.ttl":
if "ttl_urukul" in k:
continue
channel = v["arguments"]["channel"]
force_out = v["class"] == "TTLOut"
widget = _WidgetDesc(k, comment, _TTLWidget, (channel, force_out, k))
description.add(widget)
_setup_ttl(k, v, description)
elif (v["module"] == "artiq.coredevice.ad9914" and v["class"] == "AD9914"):
bus_channel = v["arguments"]["bus_channel"]
channel = v["arguments"]["channel"]
dds_sysclk = v["arguments"]["sysclk"]
model = _DDSModel(v["class"], dds_sysclk)
widget = _WidgetDesc(k, comment, _DDSWidget,
(k, bus_channel, channel, model))
description.add(widget)
_setup_ad9914(k, v, description)
elif (v["module"] == "artiq.coredevice.ad9910" and v["class"] == "AD9910") or \
(v["module"] == "artiq.coredevice.ad9912" and v["class"] == "AD9912"):
channel = v["arguments"]["chip_select"] - 4
if channel < 0:
continue
dds_cpld = v["arguments"]["cpld_device"]
spi_dev = ddb[dds_cpld]["arguments"]["spi_device"]
bus_channel = ddb[spi_dev]["arguments"]["channel"]
pll = v["arguments"]["pll_n"]
refclk = ddb[dds_cpld]["arguments"]["refclk"]
clk_div = v["arguments"].get("clk_div", 0)
model = _DDSModel(v["class"], refclk, dds_cpld, pll, clk_div)
widget = _WidgetDesc(k, comment, _DDSWidget,
(k, bus_channel, channel, model))
description.add(widget)
_setup_urukul(k, v, description, ddb)
elif (v["module"] == "artiq.coredevice.ad53xx" and v["class"] == "AD53xx") or \
(v["module"] == "artiq.coredevice.zotino" and v["class"] == "Zotino"):
spi_device = v["arguments"]["spi_device"]
spi_device = ddb[spi_device]
while isinstance(spi_device, str):
spi_device = ddb[spi_device]
spi_channel = spi_device["arguments"]["channel"]
for channel in range(32):
widget = _WidgetDesc((k, channel), comment, _DACWidget,
(spi_channel, channel, k))
description.add(widget)
_setup_dac(k, v, description, ddb)
elif v["type"] == "controller" and k == "core_moninj":
mi_addr = v["host"]
mi_port = v.get("port_proxy", 1383)
@ -437,16 +448,14 @@ class _DeviceManager:
self.schedule_ctl = schedule_ctl
self.ddb = dict()
self.description = set()
self.widgets_by_uid = dict()
# only modified by notify_ddb
self.description = dict()
self.displayed_channels = dict()
self.dds_sysclk = 0
self.ttl_cb = lambda: None
self.ttl_widgets = dict()
self.dds_cb = lambda: None
self.dds_widgets = dict()
self.dac_cb = lambda: None
self.dac_widgets = dict()
self.refresh_display_cb = lambda: None
def init_ddb(self, ddb):
self.ddb = ddb
@ -454,56 +463,13 @@ class _DeviceManager:
def notify_ddb(self, mod):
mi_addr, mi_port, description = setup_from_ddb(self.ddb)
if (mi_addr, mi_port) != (self.mi_addr, self.mi_port):
if (mi_addr, mi_port, description) != (self.mi_addr, self.mi_port, self.description):
self.mi_addr = mi_addr
self.mi_port = mi_port
self.description = description
self.refresh_display_cb()
self.reconnect_mi.set()
for to_remove in self.description - description:
widget = self.widgets_by_uid[to_remove.uid]
del self.widgets_by_uid[to_remove.uid]
if isinstance(widget, _TTLWidget):
self.setup_ttl_monitoring(False, widget.channel)
widget.deleteLater()
del self.ttl_widgets[widget.channel]
self.ttl_cb()
elif isinstance(widget, _DDSWidget):
self.setup_dds_monitoring(False, widget.bus_channel, widget.channel)
widget.deleteLater()
del self.dds_widgets[(widget.bus_channel, widget.channel)]
self.dds_cb()
elif isinstance(widget, _DACWidget):
self.setup_dac_monitoring(False, widget.spi_channel, widget.channel)
widget.deleteLater()
del self.dac_widgets[(widget.spi_channel, widget.channel)]
self.dac_cb()
else:
raise ValueError
for to_add in description - self.description:
widget = to_add.cls(self, *to_add.arguments)
if to_add.comment is not None:
widget.setToolTip(to_add.comment)
self.widgets_by_uid[to_add.uid] = widget
if isinstance(widget, _TTLWidget):
self.ttl_widgets[widget.channel] = widget
self.ttl_cb()
self.setup_ttl_monitoring(True, widget.channel)
elif isinstance(widget, _DDSWidget):
self.dds_widgets[(widget.bus_channel, widget.channel)] = widget
self.dds_cb()
self.setup_dds_monitoring(True, widget.bus_channel, widget.channel)
elif isinstance(widget, _DACWidget):
self.dac_widgets[(widget.spi_channel, widget.channel)] = widget
self.dac_cb()
self.setup_dac_monitoring(True, widget.spi_channel, widget.channel)
else:
raise ValueError
self.description = description
def ttl_set_mode(self, channel, mode):
if self.mi_connection is not None:
widget = self.ttl_widgets[channel]
@ -655,6 +621,15 @@ class _DeviceManager:
"ToggleDDS",
"Toggle DDS {} {}".format(dds_channel, "on" if sw else "off"))
def setup_monitoring(self, uid, enable):
widget_type = self.description[uid].widget_type
if widget_type == "TTL":
self.setup_ttl_monitoring(enable, uid[0])
elif widget_type == "DDS":
self.setup_dds_monitoring(enable, *uid)
elif widget_type == "DAC":
self.setup_dac_monitoring(enable, *uid)
def setup_ttl_monitoring(self, enable, channel):
if self.mi_connection is not None:
self.mi_connection.monitor_probe(enable, channel, TTLProbe.level.value)
@ -673,30 +648,15 @@ class _DeviceManager:
self.mi_connection.monitor_probe(enable, spi_channel, channel)
def monitor_cb(self, channel, probe, value):
if channel in self.ttl_widgets:
widget = self.ttl_widgets[channel]
if probe == TTLProbe.level.value:
widget.cur_level = bool(value)
elif probe == TTLProbe.oe.value:
widget.cur_oe = bool(value)
widget.refresh_display()
elif (channel, probe) in self.dds_widgets:
widget = self.dds_widgets[(channel, probe)]
widget.dds_model.monitor_update(probe, value)
widget.refresh_display()
elif (channel, probe) in self.dac_widgets:
widget = self.dac_widgets[(channel, probe)]
widget.cur_value = value
widget.refresh_display()
if (channel, None) in self.displayed_channels:
self.displayed_channels[(channel, None)].monitor_cb(probe, value)
elif (channel, probe) in self.displayed_channels:
self.displayed_channels[(channel, probe)].monitor_cb(probe, value)
def injection_status_cb(self, channel, override, value):
if channel in self.ttl_widgets:
widget = self.ttl_widgets[channel]
if override == TTLOverride.en.value:
widget.cur_override = bool(value)
if override == TTLOverride.level.value:
widget.cur_override_level = bool(value)
widget.refresh_display()
if (channel, None) in self.displayed_channels and \
self.description[(channel, None)].widget_type == "TTL":
self.displayed_channels[(channel, None)].injection_status_cb(override, value)
def disconnect_cb(self):
logger.error("lost connection to moninj")
@ -722,12 +682,8 @@ class _DeviceManager:
logger.info("ARTIQ dashboard connected to moninj (%s)",
self.mi_addr)
self.mi_connection = new_mi_connection
for ttl_channel in self.ttl_widgets.keys():
self.setup_ttl_monitoring(True, ttl_channel)
for bus_channel, channel in self.dds_widgets.keys():
self.setup_dds_monitoring(True, bus_channel, channel)
for spi_channel, channel in self.dac_widgets.keys():
self.setup_dac_monitoring(True, spi_channel, channel)
for key in self.displayed_channels:
self.setup_monitoring(key, True)
async def close(self):
self.mi_connector_task.cancel()
@ -739,38 +695,28 @@ class _DeviceManager:
await self.mi_connection.close()
class _MonInjDock(QtWidgets.QDockWidget):
def __init__(self, name):
QtWidgets.QDockWidget.__init__(self, name)
self.setObjectName(name)
class MonInjDock(QtWidgets.QDockWidget):
def __init__(self, schedule_ctl):
QtWidgets.QDockWidget.__init__(self, "MonInj")
self.setObjectName("MonInj")
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
QtWidgets.QDockWidget.DockWidgetFloatable)
def layout_widgets(self, widgets):
scroll_area = QtWidgets.QScrollArea()
scroll_area.setWidgetResizable(True)
self.setWidget(scroll_area)
grid = FlowLayout()
self.grid = FlowLayout()
grid_widget = QtWidgets.QWidget()
grid_widget.setLayout(grid)
for widget in sorted(widgets, key=lambda w: w.sort_key()):
grid.addWidget(widget)
scroll_area.setWidgetResizable(True)
grid_widget.setLayout(self.grid)
scroll_area.setWidget(grid_widget)
class MonInj:
def __init__(self, schedule_ctl):
self.ttl_dock = _MonInjDock("TTL")
self.dds_dock = _MonInjDock("DDS")
self.dac_dock = _MonInjDock("DAC")
self.dm = _DeviceManager(schedule_ctl)
self.dm.ttl_cb = lambda: self.ttl_dock.layout_widgets(self.dm.ttl_widgets.values())
self.dm.dds_cb = lambda: self.dds_dock.layout_widgets(self.dm.dds_widgets.values())
self.dm.dac_cb = lambda: self.dac_dock.layout_widgets(self.dm.dac_widgets.values())
self.dm.refresh_display_cb = self.refresh_display_cb
def layout_widgets(self, widgets):
for widget in sorted(widgets, key=lambda w: w.sort_key()):
self.grid.addWidget(widget)
async def stop(self):
if self.dm is not None:

View File

@ -15,9 +15,8 @@ logger = logging.getLogger(__name__)
class Model(DictSyncModel):
def __init__(self, init):
DictSyncModel.__init__(self,
["RID", "Pipeline", "Status", "Prio", "Due date",
"Revision", "File", "Class name"],
init)
["RID", "Pipeline", "Status", "Prio", "Due date",
"Revision", "File", "Class name"], init)
def sort_key(self, k, v):
# order by priority, and then by due date and RID
@ -96,14 +95,14 @@ class ScheduleDock(QtWidgets.QDockWidget):
cw = QtGui.QFontMetrics(self.font()).averageCharWidth()
h = self.table.horizontalHeader()
h.resizeSection(0, 7*cw)
h.resizeSection(1, 12*cw)
h.resizeSection(2, 16*cw)
h.resizeSection(3, 6*cw)
h.resizeSection(4, 16*cw)
h.resizeSection(5, 30*cw)
h.resizeSection(6, 20*cw)
h.resizeSection(7, 20*cw)
h.resizeSection(0, 7 * cw)
h.resizeSection(1, 12 * cw)
h.resizeSection(2, 16 * cw)
h.resizeSection(3, 6 * cw)
h.resizeSection(4, 16 * cw)
h.resizeSection(5, 30 * cw)
h.resizeSection(6, 20 * cw)
h.resizeSection(7, 20 * cw)
def set_model(self, model):
self.table_model = model
@ -143,7 +142,7 @@ class ScheduleDock(QtWidgets.QDockWidget):
selected_rid = self.table_model.row_to_key[row]
pipeline = self.table_model.backing_store[selected_rid]["pipeline"]
logger.info("Requesting termination of all "
"experiments in pipeline '%s'", pipeline)
"experiments in pipeline '%s'", pipeline)
rids = set()
for rid, info in self.table_model.backing_store.items():
@ -151,7 +150,6 @@ class ScheduleDock(QtWidgets.QDockWidget):
rids.add(rid)
asyncio.ensure_future(self.request_term_multiple(rids))
def save_state(self):
return bytes(self.table.horizontalHeader().saveState())

View File

@ -33,7 +33,7 @@ class ShortcutsDock(QtWidgets.QDockWidget):
for i in range(12):
row = i + 1
layout.addWidget(QtWidgets.QLabel("F" + str(i+1)), row, 0)
layout.addWidget(QtWidgets.QLabel("F" + str(i + 1)), row, 0)
label = QtWidgets.QLabel()
label.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
@ -68,7 +68,7 @@ class ShortcutsDock(QtWidgets.QDockWidget):
"open": open,
"submit": submit
}
shortcut = QtWidgets.QShortcut("F" + str(i+1), main_window)
shortcut = QtWidgets.QShortcut("F" + str(i + 1), main_window)
shortcut.setContext(QtCore.Qt.ApplicationShortcut)
shortcut.activated.connect(partial(self._activated, i))

View File

@ -500,7 +500,7 @@ pub extern fn main() -> i32 {
println!(r"|_| |_|_|____/ \___/ \____|");
println!("");
println!("MiSoC Bootloader");
println!("Copyright (c) 2017-2023 M-Labs Limited");
println!("Copyright (c) 2017-2024 M-Labs Limited");
println!("");
#[cfg(has_ethmac)]

View File

@ -226,8 +226,8 @@ def main():
smgr.register(d_applets)
broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify)
d_ttl_dds = moninj.MonInj(rpc_clients["schedule"])
atexit_register_coroutine(d_ttl_dds.stop, loop=loop)
d_moninj = moninj.MonInjDock(rpc_clients["schedule"])
atexit_register_coroutine(d_moninj.stop, loop=loop)
d_waveform = waveform.WaveformDock(
args.analyzer_proxy_timeout,
@ -237,10 +237,10 @@ def main():
atexit_register_coroutine(d_waveform.stop, loop=loop)
def init_cbs(ddb):
d_ttl_dds.dm.init_ddb(ddb)
d_moninj.dm.init_ddb(ddb)
d_waveform.init_ddb(ddb)
return ddb
devices_sub = Subscriber("devices", init_cbs, [d_ttl_dds.dm.notify_ddb, d_waveform.notify_ddb])
devices_sub = Subscriber("devices", init_cbs, [d_moninj.dm.notify_ddb, d_waveform.notify_ddb])
loop.run_until_complete(devices_sub.connect(args.server, args.port_notify))
atexit_register_coroutine(devices_sub.close, loop=loop)
@ -260,8 +260,7 @@ def main():
# lay out docks
right_docks = [
d_explorer, d_shortcuts,
d_ttl_dds.ttl_dock, d_ttl_dds.dds_dock, d_ttl_dds.dac_dock,
d_explorer, d_shortcuts, d_moninj,
d_datasets, d_applets, d_waveform, d_interactive_args
]
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0])
@ -280,8 +279,7 @@ def main():
atexit_register_coroutine(smgr.stop, loop=loop)
# work around for https://github.com/m-labs/artiq/issues/1307
d_ttl_dds.ttl_dock.show()
d_ttl_dds.dds_dock.show()
d_moninj.show()
# create first log dock if not already in state
d_log0 = logmgr.first_log_dock()

View File

@ -202,7 +202,6 @@ class EnumerationEntry(QtWidgets.QWidget):
def __init__(self, argument):
QtWidgets.QWidget.__init__(self)
disable_scroll_wheel(self)
layout = QtWidgets.QHBoxLayout()
self.setLayout(layout)
procdesc = argument["desc"]
@ -221,6 +220,7 @@ class EnumerationEntry(QtWidgets.QWidget):
self.btn_group.idClicked.connect(submit)
else:
self.combo_box = QtWidgets.QComboBox()
disable_scroll_wheel(self.combo_box)
self.combo_box.addItems(choices)
idx = choices.index(argument["state"])
self.combo_box.setCurrentIndex(idx)

View File

@ -28,10 +28,10 @@ from artiq.master.worker_db import DeviceManager, DatasetManager, DummyDevice
from artiq.language.environment import (
is_public_experiment, TraceArgumentManager, ProcessArgumentManager
)
from artiq.language.core import set_watchdog_factory, TerminationRequested
from artiq.language.core import host_only, set_watchdog_factory, TerminationRequested
from artiq.language.types import TBool
from artiq.compiler import import_cache
from artiq.coredevice.core import CompileError, host_only, _render_diagnostic
from artiq.coredevice.core import CompileError, _render_diagnostic
from artiq import __version__ as artiq_version

View File

@ -97,7 +97,7 @@ master_doc = 'index'
# General information about the project.
project = 'ARTIQ'
copyright = '2014-2023, M-Labs Limited'
copyright = '2014-2024, M-Labs Limited'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the

View File

@ -27,4 +27,4 @@ Website: https://m-labs.hk/artiq
`Cite ARTIQ <http://dx.doi.org/10.5281/zenodo.51303>`_ as ``Bourdeauducq, Sébastien et al. (2016). ARTIQ 1.0. Zenodo. 10.5281/zenodo.51303``.
Copyright (C) 2014-2023 M-Labs Limited. Licensed under GNU LGPL version 3+.
Copyright (C) 2014-2024 M-Labs Limited. Licensed under GNU LGPL version 3+.