From e5e4d55f84ef7caec126c5df442a7fdd85af9a1c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 16 Mar 2022 08:28:31 +0800 Subject: [PATCH 01/25] mgmt: fix config write error message --- artiq/coredevice/comm_mgmt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/coredevice/comm_mgmt.py b/artiq/coredevice/comm_mgmt.py index 7d8ef6f38..793b44a75 100644 --- a/artiq/coredevice/comm_mgmt.py +++ b/artiq/coredevice/comm_mgmt.py @@ -169,7 +169,7 @@ class CommMgmt: self._write_bytes(value) ty = self._read_header() if ty == Reply.Error: - raise IOError("Flash storage is full") + raise IOError("Device failed to write config. More information may be available in the log.") elif ty != Reply.Success: raise IOError("Incorrect reply from device: {} (expected {})". format(ty, Reply.Success)) From c1c2d21ba7841e2ff0c6fca71e67286b9face3a4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 16 Mar 2022 21:20:48 +0800 Subject: [PATCH 02/25] flake: fix error message when Vivado is not found --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 842c16a07..261f52853 100644 --- a/flake.nix +++ b/flake.nix @@ -245,7 +245,7 @@ vivado = pkgs.buildFHSUserEnv { name = "vivado"; targetPkgs = vivadoDeps; - profile = "source /opt/Xilinx/Vivado/2021.1/settings64.sh"; + profile = "set -e; source /opt/Xilinx/Vivado/2021.1/settings64.sh"; runScript = "vivado"; }; From 1a26eb8cf22b9a0146cd269bcc69b59eea442c81 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 16 Mar 2022 21:21:43 +0800 Subject: [PATCH 03/25] coredevice: only print version mismatch warning when relevant --- artiq/coredevice/comm_kernel.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/artiq/coredevice/comm_kernel.py b/artiq/coredevice/comm_kernel.py index e6551cb0a..0b5dd84b7 100644 --- a/artiq/coredevice/comm_kernel.py +++ b/artiq/coredevice/comm_kernel.py @@ -171,6 +171,16 @@ class CommKernelDummy: pass +def incompatible_versions(v1, v2): + if v1.endswith(".beta") or v2.endswith(".beta"): + # Beta branches may introduce breaking changes. Check version strictly. + return v1 != v2 + else: + # On stable branches, runtime/software protocol backward compatibility is kept. + # Runtime and software with the same major version number are compatible. + return v1.split(".", maxsplit=1)[0] != v2.split(".", maxsplit=1)[0] + + class CommKernel: warned_of_mismatch = False @@ -347,7 +357,7 @@ class CommKernel: runtime_id = self._read(4) if runtime_id == b"AROR": gateware_version = self._read_string().split(";")[0] - if gateware_version != software_version and not self.warned_of_mismatch: + if not self.warned_of_mismatch and incompatible_versions(gateware_version, software_version): logger.warning("Mismatch between gateware (%s) " "and software (%s) versions", gateware_version, software_version) From a159ef642dc98f154c1591d94bafcc825a3dc3ed Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 16 Mar 2022 21:22:35 +0800 Subject: [PATCH 04/25] drtio: demote default routing table message to info --- artiq/firmware/libboard_artiq/drtio_routing.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/libboard_artiq/drtio_routing.rs b/artiq/firmware/libboard_artiq/drtio_routing.rs index 10ce489b1..68836386f 100644 --- a/artiq/firmware/libboard_artiq/drtio_routing.rs +++ b/artiq/firmware/libboard_artiq/drtio_routing.rs @@ -64,12 +64,14 @@ pub fn config_routing_table(default_n_links: usize) -> RoutingTable { } } return true; + } else { + warn!("length of the configured routing table is incorrect"); } } false }); if !ok { - warn!("could not read routing table from configuration, using default"); + info!("could not read routing table from configuration, using default"); } info!("routing table: {}", ret); ret From aff569b2c3662a9eb98b07efa75f369d3ee84e32 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 17 Mar 2022 19:56:07 +0800 Subject: [PATCH 05/25] firmware: support 64-bit moninj probes --- artiq/coredevice/comm_moninj.py | 5 ++--- artiq/firmware/libproto_artiq/drtioaux_proto.rs | 6 +++--- artiq/firmware/libproto_artiq/moninj_proto.rs | 4 ++-- artiq/firmware/runtime/moninj.rs | 8 ++++---- artiq/firmware/satman/main.rs | 4 ++-- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/artiq/coredevice/comm_moninj.py b/artiq/coredevice/comm_moninj.py index f03e91bbc..d25da82e8 100644 --- a/artiq/coredevice/comm_moninj.py +++ b/artiq/coredevice/comm_moninj.py @@ -84,9 +84,8 @@ class CommMonInj: if not ty: return if ty == b"\x00": - payload = await self._reader.readexactly(9) - channel, probe, value = struct.unpack( - self.endian + "lbl", payload) + payload = await self._reader.readexactly(13) + channel, probe, value = struct.unpack(self.endian + "lbq", payload) self.monitor_cb(channel, probe, value) elif ty == b"\x01": payload = await self._reader.readexactly(6) diff --git a/artiq/firmware/libproto_artiq/drtioaux_proto.rs b/artiq/firmware/libproto_artiq/drtioaux_proto.rs index 36e2cb45b..dbfe4a5ad 100644 --- a/artiq/firmware/libproto_artiq/drtioaux_proto.rs +++ b/artiq/firmware/libproto_artiq/drtioaux_proto.rs @@ -34,7 +34,7 @@ pub enum Packet { RoutingAck, MonitorRequest { destination: u8, channel: u16, probe: u8 }, - MonitorReply { value: u32 }, + MonitorReply { value: u64 }, InjectionRequest { destination: u8, channel: u16, overrd: u8, value: u8 }, InjectionStatusRequest { destination: u8, channel: u16, overrd: u8 }, InjectionStatusReply { value: u8 }, @@ -105,7 +105,7 @@ impl Packet { probe: reader.read_u8()? }, 0x41 => Packet::MonitorReply { - value: reader.read_u32()? + value: reader.read_u64()? }, 0x50 => Packet::InjectionRequest { destination: reader.read_u8()?, @@ -259,7 +259,7 @@ impl Packet { }, Packet::MonitorReply { value } => { writer.write_u8(0x41)?; - writer.write_u32(value)?; + writer.write_u64(value)?; }, Packet::InjectionRequest { destination, channel, overrd, value } => { writer.write_u8(0x50)?; diff --git a/artiq/firmware/libproto_artiq/moninj_proto.rs b/artiq/firmware/libproto_artiq/moninj_proto.rs index dba2f84bc..c5b76f2bd 100644 --- a/artiq/firmware/libproto_artiq/moninj_proto.rs +++ b/artiq/firmware/libproto_artiq/moninj_proto.rs @@ -40,7 +40,7 @@ pub enum HostMessage { #[derive(Debug)] pub enum DeviceMessage { - MonitorStatus { channel: u32, probe: u8, value: u32 }, + MonitorStatus { channel: u32, probe: u8, value: u64 }, InjectionStatus { channel: u32, overrd: u8, value: u8 } } @@ -82,7 +82,7 @@ impl DeviceMessage { writer.write_u8(0)?; writer.write_u32(channel)?; writer.write_u8(probe)?; - writer.write_u32(value)?; + writer.write_u64(value)?; }, DeviceMessage::InjectionStatus { channel, overrd, value } => { writer.write_u8(1)?; diff --git a/artiq/firmware/runtime/moninj.rs b/artiq/firmware/runtime/moninj.rs index c1bba04fc..76a209f63 100644 --- a/artiq/firmware/runtime/moninj.rs +++ b/artiq/firmware/runtime/moninj.rs @@ -13,12 +13,12 @@ use board_artiq::drtio_routing; mod local_moninj { use board_misoc::csr; - pub fn read_probe(channel: u16, probe: u8) -> u32 { + pub fn read_probe(channel: u16, probe: u8) -> u64 { unsafe { csr::rtio_moninj::mon_chan_sel_write(channel as _); csr::rtio_moninj::mon_probe_sel_write(probe); csr::rtio_moninj::mon_value_update_write(1); - csr::rtio_moninj::mon_value_read() as u32 + csr::rtio_moninj::mon_value_read() as u64 } } @@ -41,7 +41,7 @@ mod local_moninj { #[cfg(not(has_rtio_moninj))] mod local_moninj { - pub fn read_probe(_channel: u16, _probe: u8) -> u32 { 0 } + pub fn read_probe(_channel: u16, _probe: u8) -> u64 { 0 } pub fn inject(_channel: u16, _overrd: u8, _value: u8) { } @@ -54,7 +54,7 @@ mod remote_moninj { use rtio_mgt::drtio; use sched::{Io, Mutex}; - pub fn read_probe(io: &Io, aux_mutex: &Mutex, linkno: u8, destination: u8, channel: u16, probe: u8) -> u32 { + pub fn read_probe(io: &Io, aux_mutex: &Mutex, linkno: u8, destination: u8, channel: u16, probe: u8) -> u64 { let reply = drtio::aux_transact(io, aux_mutex, linkno, &drtioaux::Packet::MonitorRequest { destination: destination, channel: channel, diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index a99e3d5b3..10beb6695 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -207,13 +207,13 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater], csr::rtio_moninj::mon_chan_sel_write(channel as _); csr::rtio_moninj::mon_probe_sel_write(probe); csr::rtio_moninj::mon_value_update_write(1); - value = csr::rtio_moninj::mon_value_read(); + value = csr::rtio_moninj::mon_value_read() as u64; } #[cfg(not(has_rtio_moninj))] { value = 0; } - let reply = drtioaux::Packet::MonitorReply { value: value as u32 }; + let reply = drtioaux::Packet::MonitorReply { value: value }; drtioaux::send(0, &reply) }, drtioaux::Packet::InjectionRequest { destination: _destination, channel, overrd, value } => { From 710786388c1072708b6d63004d9b2c144c9ba602 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 17 Mar 2022 21:09:48 +0800 Subject: [PATCH 06/25] update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 3cb5b834f..7d051edba 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1646588256, - "narHash": "sha256-ZHljmNlt19nSm0Mz8fx6QEhddKUkU4hhwFmfNmGn+EY=", + "lastModified": 1647282937, + "narHash": "sha256-K8Oo6QyFCfiEWTRpQVfzcwI3YNMKlz6Tu8rr+o3rzRQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2ebb6c1e5ae402ba35cca5eec58385e5f1adea04", + "rev": "64fc73bd74f04d3e10cb4e70e1c65b92337e76db", "type": "github" }, "original": { From bbb2c751947386e2cf3ba913c0fc41903e89e6be Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 18 Mar 2022 17:01:51 +0800 Subject: [PATCH 07/25] add aqctl_moninj_proxy --- artiq/frontend/aqctl_moninj_proxy.py | 225 +++++++++++++++++++++++++++ artiq/test/test_frontends.py | 2 +- doc/manual/default_network_ports.rst | 4 +- doc/manual/utilities.rst | 8 + setup.py | 1 + 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100755 artiq/frontend/aqctl_moninj_proxy.py diff --git a/artiq/frontend/aqctl_moninj_proxy.py b/artiq/frontend/aqctl_moninj_proxy.py new file mode 100755 index 000000000..760be7020 --- /dev/null +++ b/artiq/frontend/aqctl_moninj_proxy.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 + +import argparse +import logging +import asyncio +import struct +from enum import Enum + +from sipyco.asyncio_tools import AsyncioServer +from sipyco.pc_rpc import Server +from sipyco import common_args + +from artiq.coredevice.comm_moninj import CommMonInj + + +logger = logging.getLogger(__name__) + + +class EventType(Enum): + PROBE = 0 + INJECTION = 1 + + +class MonitorMux: + def __init__(self): + self.listeners = dict() + self.comm_moninj = None + + def _monitor(self, listener, event): + try: + listeners = self.listeners[event] + except KeyError: + listeners = [] + self.listeners[event] = listeners + if event[0] == EventType.PROBE: + logger.debug("starting monitoring channel %d probe %d", event[1], event[2]) + self.comm_moninj.monitor_probe(True, event[1], event[2]) + elif event[0] == EventType.INJECTION: + logger.debug("starting monitoring channel %d injection %d", event[1], event[2]) + self.comm_moninj.monitor_injection(True, event[1], event[2]) + else: + raise ValueError + if listener in listeners: + logger.warning("listener trying to subscribe twice to %s", event) + else: + listeners.append(listener) + + def _unmonitor(self, listener, event): + try: + listeners = self.listeners[event] + except KeyError: + listeners = [] + try: + listeners.remove(listener) + except ValueError: + logger.warning("listener trying to unsubscribe from %s, but was not subscribed", event) + return + if not listeners: + del self.listeners[event] + if event[0] == EventType.PROBE: + logger.debug("stopped monitoring channel %d probe %d", event[1], event[2]) + self.comm_moninj.monitor_probe(False, event[1], event[2]) + elif event[0] == EventType.INJECTION: + logger.debug("stopped monitoring channel %d injection %d", event[1], event[2]) + self.comm_moninj.monitor_injection(False, event[1], event[2]) + else: + raise ValueError + + def monitor_probe(self, listener, enable, channel, probe): + if enable: + self._monitor(listener, (EventType.PROBE, channel, probe)) + else: + self._unmonitor(listener, (EventType.PROBE, channel, probe)) + + def monitor_injection(self, listener, enable, channel, overrd): + if enable: + self._monitor(listener, (EventType.INJECTION, channel, overrd)) + else: + self._unmonitor(listener, (EventType.INJECTION, channel, overrd)) + + def _event_cb(self, event, value): + try: + listeners = self.listeners[event] + except KeyError: + # We may still receive buffered events shortly after an unsubscription. They can be ignored. + logger.debug("received event %s but no listener", event) + listeners = [] + for listener in listeners: + if event[0] == EventType.PROBE: + listener.monitor_cb(event[1], event[2], value) + elif event[1] == EventType.MONITOR: + listener.injection_status_cb(event[1], event[2], value) + else: + raise ValueError + + def monitor_cb(self, channel, probe, value): + self._event_cb((EventType.PROBE, channel, probe), value) + + def injection_status_cb(self, channel, override, value): + self._event_cb((EventType.INJECTION, channel, override), value) + + def remove_listener(self, listener): + for event, listeners in list(self.listeners.items()): + try: + listeners.remove(listener) + except ValueError: + pass + if not listeners: + del self.listeners[event] + if event[0] == EventType.PROBE: + logger.debug("stopped monitoring channel %d probe %d", event[1], event[2]) + self.comm_moninj.monitor_probe(False, event[1], event[2]) + elif event[0] == EventType.INJECTION: + logger.debug("stopped monitoring channel %d injection %d", event[1], event[2]) + self.comm_moninj.monitor_injection(False, event[1], event[2]) + else: + raise ValueError + + +class ProxyConnection: + def __init__(self, monitor_mux, reader, writer): + self.monitor_mux = monitor_mux + self.reader = reader + self.writer = writer + + async def handle(self): + try: + while True: + ty = await self.reader.read(1) + if not ty: + return + if ty == "\x00": # MonitorProbe + packet = await self.reader.readexactly(6) + enable, channel, probe = struct.unpack(" Date: Sat, 19 Mar 2022 19:06:12 +0800 Subject: [PATCH 08/25] aqctl_moninj_proxy: fix all major bugs --- artiq/frontend/aqctl_moninj_proxy.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/artiq/frontend/aqctl_moninj_proxy.py b/artiq/frontend/aqctl_moninj_proxy.py index 760be7020..12767891c 100755 --- a/artiq/frontend/aqctl_moninj_proxy.py +++ b/artiq/frontend/aqctl_moninj_proxy.py @@ -88,7 +88,7 @@ class MonitorMux: for listener in listeners: if event[0] == EventType.PROBE: listener.monitor_cb(event[1], event[2], value) - elif event[1] == EventType.MONITOR: + elif event[0] == EventType.INJECTION: listener.injection_status_cb(event[1], event[2], value) else: raise ValueError @@ -129,19 +129,19 @@ class ProxyConnection: ty = await self.reader.read(1) if not ty: return - if ty == "\x00": # MonitorProbe + if ty == b"\x00": # MonitorProbe packet = await self.reader.readexactly(6) enable, channel, probe = struct.unpack(" Date: Sat, 19 Mar 2022 19:25:21 +0800 Subject: [PATCH 09/25] add aqctl_moninj_proxy to device dbs --- artiq/examples/kasli/device_db.py | 7 +++++++ artiq/examples/kasli_drtioswitching/device_db.py | 7 +++++++ artiq/examples/kasli_sawgmaster/device_db.py | 7 +++++++ artiq/examples/kasli_suservo/device_db.py | 7 +++++++ artiq/examples/kc705_nist_clock/device_db.py | 7 +++++++ artiq/examples/metlino_sayma_ttl/device_db.py | 7 +++++++ artiq/examples/sayma_master/device_db.py | 7 +++++++ 7 files changed, 49 insertions(+) diff --git a/artiq/examples/kasli/device_db.py b/artiq/examples/kasli/device_db.py index f4d39293e..a0263ee24 100644 --- a/artiq/examples/kasli/device_db.py +++ b/artiq/examples/kasli/device_db.py @@ -15,6 +15,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/kasli_drtioswitching/device_db.py b/artiq/examples/kasli_drtioswitching/device_db.py index 433eaf7bc..f9486393d 100644 --- a/artiq/examples/kasli_drtioswitching/device_db.py +++ b/artiq/examples/kasli_drtioswitching/device_db.py @@ -13,6 +13,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/kasli_sawgmaster/device_db.py b/artiq/examples/kasli_sawgmaster/device_db.py index 4cba2bbd2..1c555fdea 100644 --- a/artiq/examples/kasli_sawgmaster/device_db.py +++ b/artiq/examples/kasli_sawgmaster/device_db.py @@ -13,6 +13,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/kasli_suservo/device_db.py b/artiq/examples/kasli_suservo/device_db.py index f0d3a48a2..c52b82a94 100644 --- a/artiq/examples/kasli_suservo/device_db.py +++ b/artiq/examples/kasli_suservo/device_db.py @@ -13,6 +13,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/kc705_nist_clock/device_db.py b/artiq/examples/kc705_nist_clock/device_db.py index bf9637d32..1930f584b 100644 --- a/artiq/examples/kc705_nist_clock/device_db.py +++ b/artiq/examples/kc705_nist_clock/device_db.py @@ -17,6 +17,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/metlino_sayma_ttl/device_db.py b/artiq/examples/metlino_sayma_ttl/device_db.py index c8c3acb8e..317173cd3 100644 --- a/artiq/examples/metlino_sayma_ttl/device_db.py +++ b/artiq/examples/metlino_sayma_ttl/device_db.py @@ -13,6 +13,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", diff --git a/artiq/examples/sayma_master/device_db.py b/artiq/examples/sayma_master/device_db.py index 51eede704..4ce3f1be0 100644 --- a/artiq/examples/sayma_master/device_db.py +++ b/artiq/examples/sayma_master/device_db.py @@ -13,6 +13,13 @@ device_db = { "port": 1068, "command": "aqctl_corelog -p {port} --bind {bind} " + core_addr }, + "core_moninj": { + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {port_proxy} --port-control {port} --bind {bind} " + core_addr + }, "core_cache": { "type": "local", "module": "artiq.coredevice.cache", From 6a49b8cb58ab4dd873f2c0335ea4a1581445ce75 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 19:53:38 +0800 Subject: [PATCH 10/25] update dependencies --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 7d051edba..4071f8abb 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1644743100, - "narHash": "sha256-XqxMq2l2DXSovV7r2k/FXjYRM3bvVl3Mjy+C1koVAx4=", + "lastModified": 1647688999, + "narHash": "sha256-K99rYlmfCZmfam4m07hLZVg7m2zT5ul62wVGdpmjciA=", "owner": "m-labs", "repo": "artiq-comtools", - "rev": "8a126dd7d0a3f2d50ae151ec633cd52587d98796", + "rev": "7eb367b2df7510dd4fa7ccba3682b2ff64a5d982", "type": "github" }, "original": { @@ -41,11 +41,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1647282937, - "narHash": "sha256-K8Oo6QyFCfiEWTRpQVfzcwI3YNMKlz6Tu8rr+o3rzRQ=", + "lastModified": 1647490331, + "narHash": "sha256-Jcc+vHNDN3KDWuzGNTl3A24ICGovPneJDejiN2t57QI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "64fc73bd74f04d3e10cb4e70e1c65b92337e76db", + "rev": "2c66a7a6e036971c4847cca424125f55b9eb0b0b", "type": "github" }, "original": { @@ -73,11 +73,11 @@ ] }, "locked": { - "lastModified": 1644649772, - "narHash": "sha256-LE9L5bDSunCPEnuf5Ed8enTAXA2vkTSmjvqPX9ILO0Y=", + "lastModified": 1647688038, + "narHash": "sha256-IceTSKu1sQB8sFmDTzvmurlEHWL1cV29N0mUY5F7vUY=", "owner": "m-labs", "repo": "sipyco", - "rev": "8e4382352bc64bd01c9db35d9c9b0ef42b8b9d3b", + "rev": "1a9a3062451f5c5b125b006d1b9bee997f986abd", "type": "github" }, "original": { From 6d92e539b175995fc527695a73ad505078fa00eb Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:33:03 +0800 Subject: [PATCH 11/25] artiq_ddb_template: add aqctl_moninj_proxy --- artiq/frontend/artiq_ddb_template.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 3d5b639ca..4fd3a543f 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -38,6 +38,13 @@ def process_header(output, description): "port": 1068, "command": "aqctl_corelog -p {{port}} --bind {{bind}} " + core_addr }}, + "core_moninj": {{ + "type": "controller", + "host": "::1", + "port_proxy": 1383, + "port": 1384, + "command": "aqctl_moninj_proxy --port-proxy {{port_proxy}} --port-control {{port}} --bind {{bind}} " + core_addr + }}, "core_cache": {{ "type": "local", "module": "artiq.coredevice.cache", From 207717c740388cc27e5e67dc4924fa6850b07ef4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:33:31 +0800 Subject: [PATCH 12/25] artiq_dashboard: fix handling of moninj comment --- artiq/dashboard/moninj.py | 53 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/artiq/dashboard/moninj.py b/artiq/dashboard/moninj.py index 2a2d420e5..246db561b 100644 --- a/artiq/dashboard/moninj.py +++ b/artiq/dashboard/moninj.py @@ -207,35 +207,34 @@ def setup_from_ddb(ddb): description = set() for k, v in ddb.items(): - comment = None - if "comment" in v: - comment = v["comment"] try: - if isinstance(v, dict) and v["type"] == "local": - if k == "core": - core_addr = v["arguments"]["host"] - elif v["module"] == "artiq.coredevice.ttl": - channel = v["arguments"]["channel"] - force_out = v["class"] == "TTLOut" - widget = _WidgetDesc(k, comment, _TTLWidget, (channel, force_out, k)) - description.add(widget) - 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"] - widget = _WidgetDesc(k, comment, _DDSWidget, (bus_channel, channel, k)) - description.add(widget) - 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)) + if isinstance(v, dict): + comment = v.get("comment") + if v["type"] == "local": + if k == "core": + core_addr = v["arguments"]["host"] + elif v["module"] == "artiq.coredevice.ttl": + channel = v["arguments"]["channel"] + force_out = v["class"] == "TTLOut" + widget = _WidgetDesc(k, comment, _TTLWidget, (channel, force_out, k)) description.add(widget) + 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"] + widget = _WidgetDesc(k, comment, _DDSWidget, (bus_channel, channel, k)) + description.add(widget) + 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) except KeyError: pass return core_addr, dds_sysclk, description From 735133a2b4a33bdf5bddb1bd2d5078ab60475263 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:36:04 +0800 Subject: [PATCH 13/25] artiq_dashboard: remove references to core device in moninj --- artiq/dashboard/moninj.py | 94 +++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/artiq/dashboard/moninj.py b/artiq/dashboard/moninj.py index 246db561b..cdfd845dd 100644 --- a/artiq/dashboard/moninj.py +++ b/artiq/dashboard/moninj.py @@ -202,7 +202,7 @@ _WidgetDesc = namedtuple("_WidgetDesc", "uid comment cls arguments") def setup_from_ddb(ddb): - core_addr = None + mi_addr = None dds_sysclk = None description = set() @@ -212,7 +212,7 @@ def setup_from_ddb(ddb): comment = v.get("comment") if v["type"] == "local": if k == "core": - core_addr = v["arguments"]["host"] + mi_addr = v["arguments"]["host"] elif v["module"] == "artiq.coredevice.ttl": channel = v["arguments"]["channel"] force_out = v["class"] == "TTLOut" @@ -237,15 +237,15 @@ def setup_from_ddb(ddb): description.add(widget) except KeyError: pass - return core_addr, dds_sysclk, description + return mi_addr, dds_sysclk, description class _DeviceManager: def __init__(self): - self.core_addr = None - self.reconnect_core = asyncio.Event() - self.core_connection = None - self.core_connector_task = asyncio.ensure_future(self.core_connector()) + self.mi_addr = None + self.reconnect_mi = asyncio.Event() + self.mi_connection = None + self.mi_connector_task = asyncio.ensure_future(self.mi_connector()) self.ddb = dict() self.description = set() @@ -264,11 +264,11 @@ class _DeviceManager: return ddb def notify(self, mod): - core_addr, dds_sysclk, description = setup_from_ddb(self.ddb) + mi_addr, dds_sysclk, description = setup_from_ddb(self.ddb) - if core_addr != self.core_addr: - self.core_addr = core_addr - self.reconnect_core.set() + if mi_addr != self.mi_addr: + self.mi_addr = mi_addr + self.reconnect_mi.set() self.dds_sysclk = dds_sysclk @@ -318,44 +318,44 @@ class _DeviceManager: self.description = description def ttl_set_mode(self, channel, mode): - if self.core_connection is not None: + if self.mi_connection is not None: widget = self.ttl_widgets[channel] if mode == "0": widget.cur_override = True widget.cur_level = False - self.core_connection.inject(channel, TTLOverride.level.value, 0) - self.core_connection.inject(channel, TTLOverride.oe.value, 1) - self.core_connection.inject(channel, TTLOverride.en.value, 1) + self.mi_connection.inject(channel, TTLOverride.level.value, 0) + self.mi_connection.inject(channel, TTLOverride.oe.value, 1) + self.mi_connection.inject(channel, TTLOverride.en.value, 1) elif mode == "1": widget.cur_override = True widget.cur_level = True - self.core_connection.inject(channel, TTLOverride.level.value, 1) - self.core_connection.inject(channel, TTLOverride.oe.value, 1) - self.core_connection.inject(channel, TTLOverride.en.value, 1) + self.mi_connection.inject(channel, TTLOverride.level.value, 1) + self.mi_connection.inject(channel, TTLOverride.oe.value, 1) + self.mi_connection.inject(channel, TTLOverride.en.value, 1) elif mode == "exp": widget.cur_override = False - self.core_connection.inject(channel, TTLOverride.en.value, 0) + self.mi_connection.inject(channel, TTLOverride.en.value, 0) else: raise ValueError # override state may have changed widget.refresh_display() def setup_ttl_monitoring(self, enable, channel): - if self.core_connection is not None: - self.core_connection.monitor_probe(enable, channel, TTLProbe.level.value) - self.core_connection.monitor_probe(enable, channel, TTLProbe.oe.value) - self.core_connection.monitor_injection(enable, channel, TTLOverride.en.value) - self.core_connection.monitor_injection(enable, channel, TTLOverride.level.value) + if self.mi_connection is not None: + self.mi_connection.monitor_probe(enable, channel, TTLProbe.level.value) + self.mi_connection.monitor_probe(enable, channel, TTLProbe.oe.value) + self.mi_connection.monitor_injection(enable, channel, TTLOverride.en.value) + self.mi_connection.monitor_injection(enable, channel, TTLOverride.level.value) if enable: - self.core_connection.get_injection_status(channel, TTLOverride.en.value) + self.mi_connection.get_injection_status(channel, TTLOverride.en.value) def setup_dds_monitoring(self, enable, bus_channel, channel): - if self.core_connection is not None: - self.core_connection.monitor_probe(enable, bus_channel, channel) + if self.mi_connection is not None: + self.mi_connection.monitor_probe(enable, bus_channel, channel) def setup_dac_monitoring(self, enable, spi_channel, channel): - if self.core_connection is not None: - self.core_connection.monitor_probe(enable, spi_channel, channel) + if self.mi_connection is not None: + self.mi_connection.monitor_probe(enable, spi_channel, channel) def monitor_cb(self, channel, probe, value): if channel in self.ttl_widgets: @@ -384,29 +384,29 @@ class _DeviceManager: widget.refresh_display() def disconnect_cb(self): - logger.error("lost connection to core device moninj") - self.reconnect_core.set() + logger.error("lost connection to moninj") + self.reconnect_mi.set() - async def core_connector(self): + async def mi_connector(self): while True: - await self.reconnect_core.wait() - self.reconnect_core.clear() - if self.core_connection is not None: - await self.core_connection.close() - self.core_connection = None - new_core_connection = CommMonInj(self.monitor_cb, self.injection_status_cb, + await self.reconnect_mi.wait() + self.reconnect_mi.clear() + if self.mi_connection is not None: + await self.mi_connection.close() + self.mi_connection = None + new_mi_connection = CommMonInj(self.monitor_cb, self.injection_status_cb, self.disconnect_cb) try: - await new_core_connection.connect(self.core_addr, 1383) + await new_mi_connection.connect(self.mi_addr, 1383) except asyncio.CancelledError: - logger.info("cancelled connection to core device moninj") + logger.info("cancelled connection to moninj") break except: - logger.error("failed to connect to core device moninj", exc_info=True) + logger.error("failed to connect to moninj", exc_info=True) await asyncio.sleep(10.) - self.reconnect_core.set() + self.reconnect_mi.set() else: - self.core_connection = new_core_connection + 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(): @@ -415,13 +415,13 @@ class _DeviceManager: self.setup_dac_monitoring(True, spi_channel, channel) async def close(self): - self.core_connector_task.cancel() + self.mi_connector_task.cancel() try: - await asyncio.wait_for(self.core_connector_task, None) + await asyncio.wait_for(self.mi_connector_task, None) except asyncio.CancelledError: pass - if self.core_connection is not None: - await self.core_connection.close() + if self.mi_connection is not None: + await self.mi_connection.close() class _MonInjDock(QtWidgets.QDockWidget): From ec1efd7af990c4d2ad94c43a389374c7c1f94583 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:50:36 +0800 Subject: [PATCH 14/25] dashboard: connect to moninj via proxy --- artiq/dashboard/moninj.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/artiq/dashboard/moninj.py b/artiq/dashboard/moninj.py index cdfd845dd..a9adc5678 100644 --- a/artiq/dashboard/moninj.py +++ b/artiq/dashboard/moninj.py @@ -211,9 +211,7 @@ def setup_from_ddb(ddb): if isinstance(v, dict): comment = v.get("comment") if v["type"] == "local": - if k == "core": - mi_addr = v["arguments"]["host"] - elif v["module"] == "artiq.coredevice.ttl": + if v["module"] == "artiq.coredevice.ttl": channel = v["arguments"]["channel"] force_out = v["class"] == "TTLOut" widget = _WidgetDesc(k, comment, _TTLWidget, (channel, force_out, k)) @@ -235,6 +233,8 @@ def setup_from_ddb(ddb): for channel in range(32): widget = _WidgetDesc((k, channel), comment, _DACWidget, (spi_channel, channel, k)) description.add(widget) + elif v["type"] == "controller" and k == "core_moninj": + mi_addr = v["host"] except KeyError: pass return mi_addr, dds_sysclk, description From d644e982c8c039d1de8237365ca31057c31c22ca Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:50:54 +0800 Subject: [PATCH 15/25] RELEASE_NOTES: update --- RELEASE_NOTES.rst | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index de797aaff..a14fafd11 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -13,31 +13,35 @@ Highlights: - HVAMP_8CH 8 channel HV amplifier for Fastino / Zotinos - Almazny mezzanine board for Mirny * Softcore targets now use the RISC-V architecture (VexRiscv) instead of OR1K (mor1kx). +* Gateware FPU is supported on KC705 and Kasli 2.0. * Faster compilation for large arrays/lists. * Phaser: - Improved documentation - Expose the DAC coarse mixer and ``sif_sync`` - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. - Add helpers to align Phaser updates to the RTIO timeline (``get_next_frame_mu()``) -* ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 +* Core device moninj is now proxied via the ``aqctl_moninj_proxy`` controller. +* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage + of compile-time options. +* Packaging via Nix Flakes. +* Firmware and gateware can now be built on-demand on the M-Labs server using ``afws_client`` + (subscribers only). +* Extended Kasli gateware JSON description with configuration for SPI over DIO. +* ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912. * On Kasli, the number of FIFO lanes in the scalable events dispatcher (SED) can now be configured in the JSON hardware description file. * ``artiq_ddb_template`` generates edge-counter keys that start with the key of the corresponding TTL device (e.g. ``ttl_0_counter`` for the edge counter on TTL device ``ttl_0``). * ``artiq_master`` now has an ``--experiment-subdir`` option to scan only a subdirectory of the repository when building the list of experiments. -* The configuration entry ``rtio_clock`` supports multiple clocking settings, deprecating the usage - of compile-time options. -* DRTIO: added support for 100MHz clock. +* Added support for 100MHz RTIO clock in DRTIO. * Previously detected RTIO async errors are reported to the host after each kernel terminates and a warning is logged. The warning is additional to the one already printed in the core device log upon detection of the error. -* Removed worker DB warning for writing a dataset that is also in the archive -* Extended Kasli gateware JSON description with configuration for SPI over DIO. - See: https://github.com/m-labs/artiq/pull/1800 +* Removed worker DB warning for writing a dataset that is also in the archive. * ``PCA9548`` I2C switch class renamed to ``I2CSwitch``, to accomodate support for PCA9547, and possibly other switches in future. Readback has been removed, and now only one channel per - switch is supported. + switch is supported. Breaking changes: @@ -51,7 +55,6 @@ Breaking changes: * Phaser: fixed coarse mixer frequency configuration * Mirny: Added extra delays in ``ADF5356.sync()``. This avoids the need of an extra delay before calling `ADF5356.init()`. -* DRTIO: Changed message alignment from 32-bits to 64-bits. * The deprecated ``set_dataset(..., save=...)`` is no longer supported. ARTIQ-6 From 922d2b16195abcd3c93809a6ce103b2b5e13bd36 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 19 Mar 2022 22:58:31 +0800 Subject: [PATCH 16/25] drop support for big-endian moninj --- artiq/coredevice/comm_moninj.py | 21 ++++++--------------- artiq/firmware/runtime/moninj.rs | 1 - artiq/frontend/aqctl_moninj_proxy.py | 1 - 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/artiq/coredevice/comm_moninj.py b/artiq/coredevice/comm_moninj.py index d25da82e8..a6b95983e 100644 --- a/artiq/coredevice/comm_moninj.py +++ b/artiq/coredevice/comm_moninj.py @@ -33,14 +33,6 @@ class CommMonInj: try: self._writer.write(b"ARTIQ moninj\n") - # get device endian - endian = await self._reader.read(1) - if endian == b"e": - self.endian = "<" - elif endian == b"E": - self.endian = ">" - else: - raise IOError("Incorrect reply from device: expected e/E.") self._receive_task = asyncio.ensure_future(self._receive_cr()) except: self._writer.close() @@ -62,19 +54,19 @@ class CommMonInj: del self._writer def monitor_probe(self, enable, channel, probe): - packet = struct.pack(self.endian + "bblb", 0, enable, channel, probe) + packet = struct.pack(" Date: Sun, 20 Mar 2022 12:58:55 +0800 Subject: [PATCH 17/25] support submitting experiments by content --- artiq/browser/files.py | 4 ++-- artiq/dashboard/experiments.py | 2 +- artiq/dashboard/schedule.py | 2 +- artiq/frontend/artiq_client.py | 17 +++++++++++++---- artiq/master/worker.py | 5 +++-- artiq/master/worker_impl.py | 29 ++++++++++++++++++++--------- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/artiq/browser/files.py b/artiq/browser/files.py index 103ca28db..e03f26483 100644 --- a/artiq/browser/files.py +++ b/artiq/browser/files.py @@ -107,7 +107,7 @@ class Hdf5FileSystemModel(QtWidgets.QFileSystemModel): v = ("artiq_version: {}\nrepo_rev: {}\nfile: {}\n" "class_name: {}\nrid: {}\nstart_time: {}").format( h5["artiq_version"][()], expid["repo_rev"], - expid["file"], expid["class_name"], + expid.get("file", ""), expid["class_name"], h5["rid"][()], start_time) return v except: @@ -179,7 +179,7 @@ class FilesDock(QtWidgets.QDockWidget): v = { "artiq_version": f["artiq_version"][()], "repo_rev": expid["repo_rev"], - "file": expid["file"], + "file": expid.get("file", ""), "class_name": expid["class_name"], "rid": f["rid"][()], "start_time": start_time, diff --git a/artiq/dashboard/experiments.py b/artiq/dashboard/experiments.py index 6095a3466..871894a66 100644 --- a/artiq/dashboard/experiments.py +++ b/artiq/dashboard/experiments.py @@ -726,7 +726,7 @@ class ExperimentManager: else: repo_match = "repo_rev" not in expid if (repo_match and - expid["file"] == file and + ("file" in expid and expid["file"] == file) and expid["class_name"] == class_name): rids.append(rid) asyncio.ensure_future(self._request_term_multiple(rids)) diff --git a/artiq/dashboard/schedule.py b/artiq/dashboard/schedule.py index 59ec64880..d6b74a0a7 100644 --- a/artiq/dashboard/schedule.py +++ b/artiq/dashboard/schedule.py @@ -48,7 +48,7 @@ class Model(DictSyncModel): else: return "Outside repo." elif column == 6: - return v["expid"]["file"] + return v["expid"].get("file", "") elif column == 7: if v["expid"]["class_name"] is None: return "" diff --git a/artiq/frontend/artiq_client.py b/artiq/frontend/artiq_client.py index 7194a4e45..993fe0ee4 100755 --- a/artiq/frontend/artiq_client.py +++ b/artiq/frontend/artiq_client.py @@ -67,6 +67,9 @@ def get_argparser(): parser_add.add_argument("-r", "--revision", default=None, help="use a specific repository revision " "(defaults to head, ignored without -R)") + parser_add.add_argument("--content", default=False, + action="store_true", + help="submit by content") parser_add.add_argument("-c", "--class-name", default=None, help="name of the class to run") parser_add.add_argument("file", metavar="FILE", @@ -134,12 +137,18 @@ def _action_submit(remote, args): expid = { "log_level": logging.WARNING + args.quiet*10 - args.verbose*10, - "file": args.file, "class_name": args.class_name, "arguments": arguments, } - if args.repository: - expid["repo_rev"] = args.revision + if args.content: + with open(args.file, "r") as f: + expid["content"] = f.read() + if args.repository: + raise ValueError("Repository cannot be used when submitting by content") + else: + expid["file"] = args.file + if args.repository: + expid["repo_rev"] = args.revision if args.timed is None: due_date = None else: @@ -207,7 +216,7 @@ def _show_schedule(schedule): row.append(expid["repo_rev"]) else: row.append("Outside repo.") - row.append(expid["file"]) + row.append(expid.get("file", "")) if expid["class_name"] is None: row.append("") else: diff --git a/artiq/master/worker.py b/artiq/master/worker.py index 36d5a202f..1267626ca 100644 --- a/artiq/master/worker.py +++ b/artiq/master/worker.py @@ -74,7 +74,7 @@ class Worker: return None def _get_log_source(self): - return "worker({},{})".format(self.rid, self.filename) + return "worker({},{})".format(self.rid, self.filename if self.filename is not None else "") async def _create_process(self, log_level): if self.ipc is not None: @@ -260,7 +260,8 @@ class Worker: async def build(self, rid, pipeline_name, wd, expid, priority, timeout=15.0): self.rid = rid - self.filename = os.path.basename(expid["file"]) + if "file" in expid: + self.filename = os.path.basename(expid["file"]) await self._create_process(expid["log_level"]) await self._worker_action( {"action": "build", diff --git a/artiq/master/worker_impl.py b/artiq/master/worker_impl.py index 0467a8096..345ee058b 100644 --- a/artiq/master/worker_impl.py +++ b/artiq/master/worker_impl.py @@ -13,6 +13,7 @@ import inspect import logging import traceback from collections import OrderedDict +import types import h5py @@ -129,11 +130,17 @@ class CCB: issue = staticmethod(make_parent_action("ccb_issue")) -def get_experiment(file, class_name): +def get_experiment_from_file(file, class_name): module = tools.file_import(file, prefix="artiq_worker_") return tools.get_experiment(module, class_name) +def get_experiment_from_content(content, class_name): + module = types.ModuleType("expcontent") + exec(content, module.__dict__) + return tools.get_experiment(module, class_name) + + register_experiment = make_parent_action("register_experiment") @@ -271,15 +278,19 @@ def main(): start_time = time.time() rid = obj["rid"] expid = obj["expid"] - if obj["wd"] is not None: - # Using repository - experiment_file = os.path.join(obj["wd"], expid["file"]) - repository_path = obj["wd"] + if "file" in expid: + if obj["wd"] is not None: + # Using repository + experiment_file = os.path.join(obj["wd"], expid["file"]) + repository_path = obj["wd"] + else: + experiment_file = expid["file"] + repository_path = None + setup_diagnostics(experiment_file, repository_path) + exp = get_experiment_from_file(experiment_file, expid["class_name"]) else: - experiment_file = expid["file"] - repository_path = None - setup_diagnostics(experiment_file, repository_path) - exp = get_experiment(experiment_file, expid["class_name"]) + setup_diagnostics("", None) + exp = get_experiment_from_content(expid["content"], expid["class_name"]) device_mgr.virtual_devices["scheduler"].set_run_info( rid, obj["pipeline_name"], expid, obj["priority"]) start_local_time = time.localtime(start_time) From 6b33f3b7197840c3d861fc988be880af7a1c2308 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 20 Mar 2022 16:09:58 +0800 Subject: [PATCH 18/25] update vivado --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 261f52853..36e223d53 100644 --- a/flake.nix +++ b/flake.nix @@ -245,7 +245,7 @@ vivado = pkgs.buildFHSUserEnv { name = "vivado"; targetPkgs = vivadoDeps; - profile = "set -e; source /opt/Xilinx/Vivado/2021.1/settings64.sh"; + profile = "set -e; source /opt/Xilinx/Vivado/2021.2/settings64.sh"; runScript = "vivado"; }; From 65d2dd017362ae0e0c7e02b0769299c23f91a346 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 20 Mar 2022 16:15:01 +0800 Subject: [PATCH 19/25] fix compilation warning --- artiq/firmware/runtime/moninj.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/artiq/firmware/runtime/moninj.rs b/artiq/firmware/runtime/moninj.rs index 61b6ddf15..6feb7ec55 100644 --- a/artiq/firmware/runtime/moninj.rs +++ b/artiq/firmware/runtime/moninj.rs @@ -2,7 +2,6 @@ use alloc::collections::btree_map::BTreeMap; use core::cell::RefCell; use io::Error as IoError; -use io::Write; use moninj_proto::*; use sched::{Io, Mutex, TcpListener, TcpStream, Error as SchedError}; use urc::Urc; From f89275b02ae5bb7b6a3d2c9e714cefd2f93e460d Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 20 Mar 2022 18:08:04 +0800 Subject: [PATCH 20/25] master: fix compiler access to source code with submit-by-content --- artiq/master/worker_impl.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/artiq/master/worker_impl.py b/artiq/master/worker_impl.py index 345ee058b..8d4ee9e36 100644 --- a/artiq/master/worker_impl.py +++ b/artiq/master/worker_impl.py @@ -13,7 +13,8 @@ import inspect import logging import traceback from collections import OrderedDict -import types +import importlib.util +import linecache import h5py @@ -135,9 +136,31 @@ def get_experiment_from_file(file, class_name): return tools.get_experiment(module, class_name) +class StringLoader: + def __init__(self, fake_filename, content): + self.fake_filename = fake_filename + self.content = content + + def get_source(self, fullname): + return self.content + + def create_module(self, spec): + return None + + def exec_module(self, module): + code = compile(self.get_source(self.fake_filename), self.fake_filename, "exec") + exec(code, module.__dict__) + + def get_experiment_from_content(content, class_name): - module = types.ModuleType("expcontent") - exec(content, module.__dict__) + fake_filename = "expcontent" + spec = importlib.util.spec_from_loader( + "expmodule", + StringLoader(fake_filename, content) + ) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + linecache.lazycache(fake_filename, module.__dict__) return tools.get_experiment(module, class_name) From a289d698838793ecc4daa4a20157483dab6ff79a Mon Sep 17 00:00:00 2001 From: Timothy Ballance Date: Mon, 21 Mar 2022 19:56:02 +0000 Subject: [PATCH 21/25] llvm_ir: fixed stack leak on ffi call --- .../compiler/transforms/llvm_ir_generator.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 197bc2cdf..7bf6037f8 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1359,11 +1359,24 @@ class LLVMIRGenerator: else: llfun = self.map(insn.static_target_function) llenv = self.llbuilder.extract_value(llclosure, 0, name="env.fun") - return llfun, [llenv] + list(llargs), {} + return llfun, [llenv] + list(llargs), {}, None def _prepare_ffi_call(self, insn): llargs = [] llarg_attrs = {} + + stack_save_needed = False + for i, arg in enumerate(insn.arguments()): + llarg = self.map(arg) + if isinstance(llarg.type, (ll.LiteralStructType, ll.IdentifiedStructType)): + stack_save_needed = True + break + + if stack_save_needed: + llcallstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) + else: + llcallstackptr = None + for i, arg in enumerate(insn.arguments()): llarg = self.map(arg) if isinstance(llarg.type, (ll.LiteralStructType, ll.IdentifiedStructType)): @@ -1399,7 +1412,7 @@ class LLVMIRGenerator: if 'nowrite' in insn.target_function().type.flags: llfun.attributes.add('inaccessiblememonly') - return llfun, list(llargs), llarg_attrs + return llfun, list(llargs), llarg_attrs, llcallstackptr def _build_rpc(self, fun_loc, fun_type, args, llnormalblock, llunwindblock): llservice = ll.Constant(lli32, fun_type.service) @@ -1535,9 +1548,9 @@ class LLVMIRGenerator: insn.arguments(), llnormalblock=None, llunwindblock=None) elif types.is_external_function(functiontyp): - llfun, llargs, llarg_attrs = self._prepare_ffi_call(insn) + llfun, llargs, llarg_attrs, llcallstackptr = self._prepare_ffi_call(insn) else: - llfun, llargs, llarg_attrs = self._prepare_closure_call(insn) + llfun, llargs, llarg_attrs, llcallstackptr = self._prepare_closure_call(insn) if self.has_sret(functiontyp): llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) @@ -1556,6 +1569,9 @@ class LLVMIRGenerator: # {} elsewhere. llresult = ll.Constant(llunit, []) + if llcallstackptr != None: + self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llcallstackptr]) + return llresult def process_Invoke(self, insn): From f91e1065862e38009a6430343f01c54faddaea42 Mon Sep 17 00:00:00 2001 From: Timothy Ballance Date: Tue, 22 Mar 2022 18:50:46 +0800 Subject: [PATCH 22/25] llvm_ir: fixed broken code in previous patch --- artiq/compiler/transforms/llvm_ir_generator.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index 7bf6037f8..50ce33f61 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -1584,9 +1584,9 @@ class LLVMIRGenerator: insn.arguments(), llnormalblock, llunwindblock) elif types.is_external_function(functiontyp): - llfun, llargs, llarg_attrs = self._prepare_ffi_call(insn) + llfun, llargs, llarg_attrs, llcallstackptr = self._prepare_ffi_call(insn) else: - llfun, llargs, llarg_attrs = self._prepare_closure_call(insn) + llfun, llargs, llarg_attrs, llcallstackptr = self._prepare_closure_call(insn) if self.has_sret(functiontyp): llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) @@ -1608,6 +1608,9 @@ class LLVMIRGenerator: # The !tbaa metadata is not legal to use with the invoke instruction, # so unlike process_Call, we do not set it here. + if llcallstackptr != None: + self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llcallstackptr]) + return llresult def _quote_listish_to_llglobal(self, value, elt_type, path, kind_name): From 866a83796a42cb9d7539e4ee6f63c909a901c8f1 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 26 Mar 2022 15:27:49 +0800 Subject: [PATCH 23/25] firmware: add UnwrapNoneError exception --- artiq/firmware/ksupport/eh_artiq.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index 30e173dc0..46403b72e 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -343,7 +343,8 @@ static EXCEPTION_ID_LOOKUP: [(&str, u32); 10] = [ ("CacheError", 6), ("SPIError", 7), ("ZeroDivisionError", 8), - ("IndexError", 9) + ("IndexError", 9), + ("UnwrapNoneError", 10), ]; pub fn get_exception_id(name: &str) -> u32 { From 723f41c78b1948c05fd6bdf7d2014e85afebe5aa Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 26 Mar 2022 20:09:11 +0800 Subject: [PATCH 24/25] runtime: fix EXCEPTION_ID_LOOKUP --- artiq/firmware/ksupport/eh_artiq.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/eh_artiq.rs b/artiq/firmware/ksupport/eh_artiq.rs index 46403b72e..19470fe70 100644 --- a/artiq/firmware/ksupport/eh_artiq.rs +++ b/artiq/firmware/ksupport/eh_artiq.rs @@ -333,7 +333,7 @@ extern fn stop_fn(_version: c_int, } } -static EXCEPTION_ID_LOOKUP: [(&str, u32); 10] = [ +static EXCEPTION_ID_LOOKUP: [(&str, u32); 11] = [ ("RuntimeError", 0), ("RTIOUnderflow", 1), ("RTIOOverflow", 2), From c82c358f3acc1d1eab942267cf13fcb13c14efc3 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 28 Mar 2022 13:33:57 +0800 Subject: [PATCH 25/25] runtime: provide/fix more libc mem functions --- artiq/firmware/ksupport/api.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/artiq/firmware/ksupport/api.rs b/artiq/firmware/ksupport/api.rs index 3e99731b4..1682f818b 100644 --- a/artiq/firmware/ksupport/api.rs +++ b/artiq/firmware/ksupport/api.rs @@ -63,7 +63,10 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(__powidf2), /* libc */ - api!(memcmp, extern { fn memcmp(a: *const u8, b: *mut u8, size: usize); }), + api!(memcpy, extern { fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; }), + api!(memmove, extern { fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; }), + api!(memset, extern { fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8; }), + api!(memcmp, extern { fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; }), /* libm */ // commented out functions are not available with the libm used here, but are available in NAR3.