Hello all, I am trying to set values to a DDS based on a preference that I specify in a dataset. I seem to be having several hurdles to go over in order to do that, and trying to see if there is a best practice method that I am unaware of.

Method 1: Static

Essentially, assigning empty static variables that can be accessed within the kernel.

from artiq.experiment import *
from artiq.language.core import kernel
import numpy as np

class DDSTest(EnvExperiment):
    F_DDS = 0
    P_DDS = 0

    def build(self):
        self.setattr_device("core")
        self.setattr_device("urukul0_ch0")

    def assign_vals_to_static(self):
        self.F_DDS = self.get_dataset("Preferences.F_DDS")
        self.P_DDS = self.get_dataset("Preferences.P_DDS")

    def prepare(self):
        self.assign_vals_to_static()

    @kernel
    def init_devices(self):
        self.core.reset()
        self.urukul0_ch0.cpld.init()
        self.urukul0_ch0.init()

        self.urukul0_ch0.set_att(self.P_DDS)
        self.urukul0_ch0.set(self.F_DDS)

        
    @kernel
    def run(self):
        self.init_devices()
        self.core.break_realtime()

        self.urukul0_ch0.sw.on()

Method 2: Using annotations?

Following the direction of this post, it looks like you should be able to use an annotation. I tried the following, only to receive the error (placed afterwards).

class DDSTest(EnvExperiment):
    def build(self):
        self.setattr_device("core")
        self.setattr_device("urukul0_ch0")

    def dataset_wrapper(self, dataset_item: str) -> float:
        return self.get_dataset(dataset_item)

    @kernel
    def init_devices(self):
        self.core.reset()
        self.urukul0_ch0.cpld.init()
        self.urukul0_ch0.init()

        self.urukul0_ch0.set_att(self.dataset_wrapper("Preferences.P_DDS"))
        self.urukul0_ch0.set(self.dataset_wrapper("Preferences.F_DDS"))

        
    @kernel
    def run(self):
        self.init_devices()
        self.core.break_realtime()

        self.urukul0_ch0.sw.on()

Error:

error: type annotation for return type, '<class 'float'>', is not an ARTIQ type.

Method 3: Using the cache?

The final method that appears viable is using the core cache to put a value into the core with a key and extract it using the get(key) method.

So the bottom line is...how do most people access their datasets from within the kernel? What is the speediest / most efficient method that you guys are seeing? If I had to guess, the cache would be the most accessible / quickest, but trying to begin developing this system using the best practice.

Thanks everyone!

    rmcgill9 error: type annotation for return type, '<class 'float'>', is not an ARTIQ type.

    You need TFloat instead (import it from artiq.language.types).
    (The new compiler NAC3 planned for ARTIQ-8 supports float)

    Method 1 will potentially give you the best runtime performance as the constants will be folded by the compiler, but the kernel cannot be precompiled.
    Methods 2 and 3 allow kernel precompilation in the prepare phase.
    The core device cache gives you faster runtime performance than a RPC, but populating the cache introduces its constraints.

      sb10q Thank you for the comments - I switched to the allowed types from artiq.language.types, but now when I pull I am getting an RTIO underflow when I try to run the first set_att line in method 2.

      2 years later

      I need a way to get datasets without adding 2 ms of delay. I'm trying to run a fast ion clock (1 ms interrogation, 2 ms deadtime) and I need to be able to interact with it while its running (do interleaved spectroscopy scans, etc). I need a way for the computer and the core to talk to each other without throwing in 2+ ms delays, which directly undercut my clock performance.

      I wish that I could call something like, "request_dataset" which would send a request to the computer from the core, with instructions for the response to get loaded into a buffer until further notice. Then I could continue issuing other instructions. Later, after a few more clock cycles, I could call "receive_dataset" and pull the response from the buffer with microsecond instead of millisecond deadtime.

      One stupid workaround is to connect an ADC channel to a DAC channel. I can run my ion clock on a kernel that uses the ADC but not the DAC. I can then run code using the DAC and communicate with the clock running on the core without any mandatory get_dataset delays by setting the voltage to some agreed upon level.

      The fact that I am considering this workaround helps illustrate just how handicapped I am by this lack of buffered low-delay core-computer communication.

      Any tips?

      22 days later

      One way would be to modify the firmware to allow the core cache (or a similar store) to be accessed by the computer in parallel with kernel execution.