I'm trying to run a simple example based on this previous post: https://forum.m-labs.hk/d/126-problem-running-two-instances-of-an-ndsp Everything is working fine, I am able to get the Hello World statements I wanted but when I tried making a loop where it prints after a one second delay:
@kernel
def run(self):
for i in range(10):
self.hello.message ("Hello, World!")
delay(1*s)

all the messages get printed out simultaneously without the delay. I am currently using the sim.core device provided from Artiq, could that be the source of the issue?

I'm hoping to use the delays as I need the accurate timing control to run other functions on non-Sinara hardware, hence the NDSP. Thanks for your help in advance!

I'm trying to run a simple example based on this previous post: https://forum.m-labs.hk/d/126-problem-running-two-instances-of-an-ndsp Everything is working fine, I am able to get the Hello World statements I wanted but when I tried making a loop where it prints after a one second delay:\

@kernel                                                                 
def run(self):                                                 
        for i in range(10):
            self.hello.message ("Hello, World!")
            delay(1*s)

all the messages get printed out simultaneously without the delay. I am currently using the sim.core device provided from Artiq, could that be the source of the issue?

I'm hoping to use the delays as I need the accurate timing control to run other functions on non-Sinara hardware, hence the NDSP. Thanks for your help in advance!

sb10q
Just checking, I've added a line self.core.wait_until_mu(now_mu()) after the delay but seems that sim.core does not have the wait_until_mu method. If I run this on actual hardware would this work then?

    edamame If I run this on actual hardware would this work then?

    Yes but you would run out of slack, so you would get RTIOUnderflow on your next ttl.on() or other timeline stuff. Follow @sb10q advices, review the difference between wall clock "rtio_counter" and timeline cursor "now" (slack is now_mu()-self.core.get_rtio_counter_mu()). When you delay() you are just pushing the cursor forward ("now") in time so the next ttl.on() is scheduled yet later. All that sheduling is performed ahead of time. As @sb10q said (or implied), what you want is spending time, ie. time.sleep() (and then "rtio_counter" will increase), and you don't even need the core device (or timeline) to spend time and have an NDSP print on screen, you can just do this:

    from artiq.experiment import *
    import time                             # for time.sleep()
    
    class hello_test(EnvExperiment):
        'Test script for hello controller, edamame version 2'
        'from https://forum.m-labs.hk/d/206-delays-using-ndsps'
    
        def build(self):
            #self.setattr_device("core")    # core not really required
            self.setattr_device("hello")
    
        #@kernel                            # requires self.core (setattr)
        def run(self):
            for i in range(10):
                self.hello.message ("Hello, World!")
                time.sleep(1)

    In the same folder of this file you could have a "nohardware" device_db.py file from the "examples" folder (I got stuck on that one, finding and learning to use it) and add the hello NDSP at the end:

    # Javier: added Tutorial hello NDSP controller
    device_db.update({
        "hello": {
            "type": "controller",
            "host": "::1",
            "port": 3210,
            "command": "python aqctl_hello.py -p {port}"
        }
    })

    You could then open 3 command shell windows, and run artiq_master -r ., artiq_ctlmgr, and artiq_dashboard, to try your new experiment. Or maybe just python aqctl_hello.py -p 3210 and artiq_run test_edamame2.py, bypassing the need for a master.
    time.sleep() is not specific for NDSPs, you`ll have to use it anytime your experiment needs spending time, be it for an NDSP or any other reason.
    Hope it helps

    7 months later

    sb10q I'm a little confused about the meaning of the decrator @kernel. Here is an example code.

    @kernel
    def run(self):
        at(5*us)
        ttl.on() # 1
        x = 1 # 2
        fun_on_host() # 3 called through RPC

    From my previous understanding, all the three statement will be sent into FIFO and wait to be executed until wall clock reaches 5us.

    But after reading this post, I find it's wrong. Now I understand it as follows. The decorator @kernel only means run() is to be executed on core device. Only the first statement will be sent into FIFO. The second and third statement will be executed immediately on the core device cpu without being sent into FIFO and waiting for the wall clock to reach 5us because they don't relate to the real-time hardware(TTL, DDS). Is my present understanding correct?

    Correct. The section in the manual explains that.