From 50767c036522084650412e5fc36348ebb0099cae Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Apr 2022 18:41:59 +0800 Subject: [PATCH] examples/kc705_nist_clock: port to NAC3 --- .../examples/kc705_nist_clock/idle_kernel.py | 21 ++++---- .../kc705_nist_clock/repository/core_pause.py | 18 +++++-- .../kc705_nist_clock/repository/dds_setter.py | 10 +++- .../kc705_nist_clock/repository/dds_test.py | 33 +++++++++---- .../kc705_nist_clock/repository/dma_blink.py | 2 + .../kc705_nist_clock/repository/handover.py | 10 +++- .../kc705_nist_clock/repository/mandelbrot.py | 22 ++++++--- .../repository/photon_histogram.py | 48 +++++++++++++------ .../kc705_nist_clock/repository/precompile.py | 2 + .../repository/speed_benchmark.py | 31 ++++++++++-- .../kc705_nist_clock/repository/tdr.py | 47 +++++++++++------- 11 files changed, 175 insertions(+), 69 deletions(-) diff --git a/artiq/examples/kc705_nist_clock/idle_kernel.py b/artiq/examples/kc705_nist_clock/idle_kernel.py index d4d746fd3..964a99674 100644 --- a/artiq/examples/kc705_nist_clock/idle_kernel.py +++ b/artiq/examples/kc705_nist_clock/idle_kernel.py @@ -1,21 +1,26 @@ from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ttl import TTLOut - +@nac3 class IdleKernel(EnvExperiment): + core: KernelInvariant[Core] + led: KernelInvariant[TTLOut] + def build(self): self.setattr_device("core") self.setattr_device("led") @kernel def run(self): - start_time = now_mu() + self.core.seconds_to_mu(500*ms) + start_time = now_mu() + self.core.seconds_to_mu(500.*ms) while self.core.get_rtio_counter_mu() < start_time: pass self.core.reset() while True: - self.led.pulse(250*ms) - delay(125*ms) - self.led.pulse(125*ms) - delay(125*ms) - self.led.pulse(125*ms) - delay(250*ms) + self.led.pulse(250.*ms) + self.core.delay(125.*ms) + self.led.pulse(125.*ms) + self.core.delay(125.*ms) + self.led.pulse(125.*ms) + self.core.delay(250.*ms) diff --git a/artiq/examples/kc705_nist_clock/repository/core_pause.py b/artiq/examples/kc705_nist_clock/repository/core_pause.py index f483f5f6b..10bb900ab 100644 --- a/artiq/examples/kc705_nist_clock/repository/core_pause.py +++ b/artiq/examples/kc705_nist_clock/repository/core_pause.py @@ -1,20 +1,30 @@ from time import sleep from artiq.experiment import * +from artiq.coredevice.core import Core + +# NAC3TODO https://git.m-labs.hk/M-Labs/nac3/issues/282 + +@rpc +def sleep_rpc(): + sleep(1) +@nac3 class CorePause(EnvExperiment): + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") self.setattr_device("scheduler") @kernel def k(self): - print("kernel starting") + print_rpc("kernel starting") while not self.scheduler.check_pause(): - print("main kernel loop running...") - sleep(1) - print("kernel exiting") + print_rpc("main kernel loop running...") + sleep_rpc() + print_rpc("kernel exiting") def run(self): while True: diff --git a/artiq/examples/kc705_nist_clock/repository/dds_setter.py b/artiq/examples/kc705_nist_clock/repository/dds_setter.py index 7f4b1447e..de2e11c8e 100644 --- a/artiq/examples/kc705_nist_clock/repository/dds_setter.py +++ b/artiq/examples/kc705_nist_clock/repository/dds_setter.py @@ -1,10 +1,16 @@ from operator import itemgetter from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ad9914 import AD9914 +@nac3 class DDSSetter(EnvExperiment): """DDS Setter""" + + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") @@ -24,10 +30,10 @@ class DDSSetter(EnvExperiment): } @kernel - def set_dds(self, dds, frequency): + def set_dds(self, dds: AD9914, frequency: float): self.core.break_realtime() dds.set(frequency) - delay(200*ms) + self.core.delay(200.*ms) def run(self): for k, v in self.dds.items(): diff --git a/artiq/examples/kc705_nist_clock/repository/dds_test.py b/artiq/examples/kc705_nist_clock/repository/dds_test.py index dceb10438..9200ba3bf 100644 --- a/artiq/examples/kc705_nist_clock/repository/dds_test.py +++ b/artiq/examples/kc705_nist_clock/repository/dds_test.py @@ -1,9 +1,22 @@ from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ad9914 import AD9914 +from artiq.coredevice.ttl import TTLOut +@nac3 class DDSTest(EnvExperiment): """DDS test""" + core: KernelInvariant[Core] + dds0: KernelInvariant[AD9914] + dds1: KernelInvariant[AD9914] + dds2: KernelInvariant[AD9914] + ttl0: KernelInvariant[TTLOut] + ttl1: KernelInvariant[TTLOut] + ttl2: KernelInvariant[TTLOut] + led: KernelInvariant[TTLOut] + def build(self): self.setattr_device("core") self.dds0 = self.get_device("ad9914dds0") @@ -17,21 +30,21 @@ class DDSTest(EnvExperiment): @kernel def run(self): self.core.reset() - delay(200*us) - self.dds1.set(120*MHz) - delay(10*us) - self.dds2.set(200*MHz) - delay(1*us) + self.core.delay(200.*us) + self.dds1.set(120.*MHz) + self.core.delay(10.*us) + self.dds2.set(200.*MHz) + self.core.delay(1.*us) for i in range(10000): - if i & 0x200: + if bool(i & 0x200): self.led.on() else: self.led.off() with parallel: with sequential: - self.dds0.set(100*MHz + 4*i*kHz) - self.ttl0.pulse(500*us) - self.ttl1.pulse(500*us) - self.ttl2.pulse(100*us) + self.dds0.set(100.*MHz + 4.*float(i)*kHz) + self.ttl0.pulse(500.*us) + self.ttl1.pulse(500.*us) + self.ttl2.pulse(100.*us) self.led.off() diff --git a/artiq/examples/kc705_nist_clock/repository/dma_blink.py b/artiq/examples/kc705_nist_clock/repository/dma_blink.py index 92c96327c..46cf8cccf 100644 --- a/artiq/examples/kc705_nist_clock/repository/dma_blink.py +++ b/artiq/examples/kc705_nist_clock/repository/dma_blink.py @@ -1,6 +1,8 @@ from artiq.experiment import * +# NAC3TODO https://git.m-labs.hk/M-Labs/nac3/issues/75 + class DMABlink(EnvExperiment): def build(self): self.setattr_device("core") diff --git a/artiq/examples/kc705_nist_clock/repository/handover.py b/artiq/examples/kc705_nist_clock/repository/handover.py index c63ef8a74..eb1e90391 100644 --- a/artiq/examples/kc705_nist_clock/repository/handover.py +++ b/artiq/examples/kc705_nist_clock/repository/handover.py @@ -1,15 +1,21 @@ from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ttl import TTLOut +@nac3 class Handover(EnvExperiment): + core: KernelInvariant[Core] + led: KernelInvariant[TTLOut] + def build(self): self.setattr_device("core") self.setattr_device("led") @kernel def blink_once(self): - delay(250*ms) - self.led.pulse(250*ms) + self.core.delay(250.*ms) + self.led.pulse(250.*ms) def run(self): self.core.reset() diff --git a/artiq/examples/kc705_nist_clock/repository/mandelbrot.py b/artiq/examples/kc705_nist_clock/repository/mandelbrot.py index 81e477548..bfe968453 100644 --- a/artiq/examples/kc705_nist_clock/repository/mandelbrot.py +++ b/artiq/examples/kc705_nist_clock/repository/mandelbrot.py @@ -1,17 +1,25 @@ import sys +from numpy import int32 + from artiq.experiment import * +from artiq.coredevice.core import Core +@nac3 class Mandelbrot(EnvExperiment): """Mandelbrot set demo""" + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") - def col(self, i): + @rpc + def col(self, i: int32): sys.stdout.write(" .,-:;i+hHM$*#@ "[i]) + @rpc def row(self): print("") @@ -22,22 +30,22 @@ class Mandelbrot(EnvExperiment): maxX = 1.0 width = 78 height = 36 - aspectRatio = 2 + aspectRatio = 2.0 - yScale = (maxX-minX)*(height/width)*aspectRatio + yScale = (maxX-minX)*(float(height)/float(width))*aspectRatio for y in range(height): for x in range(width): - c_r = minX+x*(maxX-minX)/width - c_i = y*yScale/height-yScale/2 + c_r = minX+float(x)*(maxX-minX)/float(width) + c_i = float(y)*yScale/float(height)-yScale/2.0 z_r = c_r z_i = c_i i = 0 for i in range(16): - if z_r*z_r + z_i*z_i > 4: + if z_r*z_r + z_i*z_i > 4.0: break new_z_r = (z_r*z_r)-(z_i*z_i) + c_r - z_i = 2*z_r*z_i + c_i + z_i = 2.0*z_r*z_i + c_i z_r = new_z_r self.col(i) self.row() diff --git a/artiq/examples/kc705_nist_clock/repository/photon_histogram.py b/artiq/examples/kc705_nist_clock/repository/photon_histogram.py index 4a9166a8a..f4a9be947 100644 --- a/artiq/examples/kc705_nist_clock/repository/photon_histogram.py +++ b/artiq/examples/kc705_nist_clock/repository/photon_histogram.py @@ -1,9 +1,28 @@ +from numpy import int32 + from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ad9914 import AD9914 +from artiq.coredevice.ttl import TTLOut, TTLInOut +@nac3 class PhotonHistogram(EnvExperiment): """Photon histogram""" + core: KernelInvariant[Core] + bd_dds: KernelInvariant[AD9914] + bd_sw: KernelInvariant[TTLOut] + bdd_dds: KernelInvariant[AD9914] + bdd_sw: KernelInvariant[TTLOut] + pmt: KernelInvariant[TTLInOut] + + nbins: KernelInvariant[int32] + repeats: KernelInvariant[int32] + cool_f: KernelInvariant[float] + detect_f: KernelInvariant[float] + detect_t: KernelInvariant[float] + def build(self): self.setattr_device("core") self.setattr_device("bd_dds") @@ -22,20 +41,21 @@ class PhotonHistogram(EnvExperiment): @kernel def program_cooling(self): delay_mu(-self.bd_dds.set_duration_mu) - self.bd_dds.set(200*MHz) + self.bd_dds.set(200.*MHz) delay_mu(self.bd_dds.set_duration_mu) - self.bdd_dds.set(300*MHz) + self.bdd_dds.set(300.*MHz) @kernel - def cool_detect(self): + def cool_detect(self) -> int32: with parallel: - self.bd_sw.pulse(1*ms) - self.bdd_sw.pulse(1*ms) + self.bd_sw.pulse(1.*ms) + self.bdd_sw.pulse(1.*ms) self.bd_dds.set(self.cool_f) - self.bd_sw.pulse(100*us) + self.bd_sw.pulse(100.*us) self.bd_dds.set(self.detect_f) + gate_end_mu = int64(0) with parallel: self.bd_sw.pulse(self.detect_t) gate_end_mu = self.pmt.gate_rising(self.detect_t) @@ -45,6 +65,11 @@ class PhotonHistogram(EnvExperiment): self.bdd_sw.on() return self.pmt.count(gate_end_mu) + + @rpc + def report(self, hist: list[int32], ion_present: bool): + self.set_dataset("cooling_photon_histogram", hist) + self.set_dataset("ion_present", ion_present, broadcast=True) @kernel def run(self): @@ -55,18 +80,11 @@ class PhotonHistogram(EnvExperiment): total = 0 for i in range(self.repeats): - delay(0.5*ms) + self.core.delay(0.5*ms) n = self.cool_detect() if n >= self.nbins: n = self.nbins - 1 hist[n] += 1 total += n - self.set_dataset("cooling_photon_histogram", hist) - self.set_dataset("ion_present", total > 5*self.repeats, - broadcast=True) - - -if __name__ == "__main__": - from artiq.frontend.artiq_run import run - run() + self.report(hist, total > 5*self.repeats) diff --git a/artiq/examples/kc705_nist_clock/repository/precompile.py b/artiq/examples/kc705_nist_clock/repository/precompile.py index 6bfaaf057..2ac981d25 100644 --- a/artiq/examples/kc705_nist_clock/repository/precompile.py +++ b/artiq/examples/kc705_nist_clock/repository/precompile.py @@ -1,6 +1,8 @@ from artiq.experiment import * +# NAC3TODO + class Precompile(EnvExperiment): def build(self): self.setattr_device("core") diff --git a/artiq/examples/kc705_nist_clock/repository/speed_benchmark.py b/artiq/examples/kc705_nist_clock/repository/speed_benchmark.py index 63b807390..cf28eb70c 100644 --- a/artiq/examples/kc705_nist_clock/repository/speed_benchmark.py +++ b/artiq/examples/kc705_nist_clock/repository/speed_benchmark.py @@ -1,6 +1,9 @@ import time +from numpy import int32 + from artiq.experiment import * +from artiq.coredevice.core import Core class _PayloadNOP(EnvExperiment): @@ -11,7 +14,10 @@ class _PayloadNOP(EnvExperiment): pass +@nac3 class _PayloadCoreNOP(EnvExperiment): + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") @@ -20,11 +26,15 @@ class _PayloadCoreNOP(EnvExperiment): pass +@nac3 class _PayloadCoreSend100Ints(EnvExperiment): + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") - def devnull(self, d): + @rpc + def devnull(self, d: int32): pass @kernel @@ -33,11 +43,15 @@ class _PayloadCoreSend100Ints(EnvExperiment): self.devnull(42) +@nac3 class _PayloadCoreSend1MB(EnvExperiment): + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") - def devnull(self, d): + @rpc + def devnull(self, d: list[int32]): pass @kernel @@ -46,11 +60,15 @@ class _PayloadCoreSend1MB(EnvExperiment): self.devnull(data) +@nac3 class _PayloadCorePrimes(EnvExperiment): + core: KernelInvariant[Core] + def build(self): self.setattr_device("core") - def devnull(self, d): + @rpc + def devnull(self, d: int32): pass @kernel @@ -104,9 +122,14 @@ class SpeedBenchmark(EnvExperiment): def run_without_scheduler(self, pause): payload = globals()["_Payload" + self.payload](self) + start_time = time.monotonic() for i in range(int(self.nruns)): - payload.run() + try: + payload.run() + except: + import traceback + print(traceback.format_exc()) if pause: self.core.comm.close() self.scheduler.pause() diff --git a/artiq/examples/kc705_nist_clock/repository/tdr.py b/artiq/examples/kc705_nist_clock/repository/tdr.py index 21dc9338a..fa0776371 100644 --- a/artiq/examples/kc705_nist_clock/repository/tdr.py +++ b/artiq/examples/kc705_nist_clock/repository/tdr.py @@ -1,24 +1,30 @@ # Copyright (C) 2014, 2015 Robert Jordens +from numpy import int32, int64 + from artiq.experiment import * +from artiq.coredevice.core import Core +from artiq.coredevice.ttl import TTLOut, TTLInOut +@nac3 class PulseNotReceivedError(Exception): pass +@nac3 class TDR(EnvExperiment): """Time domain reflectometer. - From ttl2 an impedance matched pulse is send onto a coax - cable with an open end. pmt0 (very short stub, high impedance) also - listens on the transmission line near ttl2. + From ttl0 an impedance matched pulse is send onto a coax + cable with an open end. ttl3 (very short stub, high impedance) also + listens on the transmission line near ttl0. - When the forward propagating pulse passes pmt0, the voltage is half of the + When the forward propagating pulse passes ttl3, the voltage is half of the logic voltage and does not register as a rising edge. Once the - rising edge is reflected at an open end (same sign) and passes by pmt0 on - its way back to ttl2, it is detected. Analogously, hysteresis leads to - detection of the falling edge once the reflection reaches pmt0 after + rising edge is reflected at an open end (same sign) and passes by ttl3 on + its way back to ttl0, it is detected. Analogously, hysteresis leads to + detection of the falling edge once the reflection reaches ttl3 after one round trip time. This works marginally and is just a proof of principle: it relies on @@ -30,10 +36,17 @@ class TDR(EnvExperiment): This is also equivalent to a loopback tester or a delay measurement. """ + + core: KernelInvariant[Core] + ttl3: KernelInvariant[TTLInOut] + ttl0: KernelInvariant[TTLOut] + + t: Kernel[list[int32]] + def build(self): self.setattr_device("core") - self.setattr_device("pmt0") - self.setattr_device("ttl2") + self.setattr_device("ttl3") + self.setattr_device("ttl0") def run(self): self.core.reset() @@ -54,20 +67,20 @@ class TDR(EnvExperiment): t_rise/1e-9, t_fall/1e-9)) @kernel - def many(self, n, p): + def many(self, n: int32, p: int64): self.core.break_realtime() for i in range(n): self.one(p) @kernel - def one(self, p): + def one(self, p: int64): t0 = now_mu() with parallel: - self.pmt0.gate_both_mu(2*p) - self.ttl2.pulse_mu(p) + self.ttl3.gate_both_mu(int64(2)*p) + self.ttl0.pulse_mu(p) for i in range(len(self.t)): - ti = self.pmt0.timestamp_mu(now_mu()) - if ti <= 0: + ti = self.ttl3.timestamp_mu(now_mu()) + if ti <= int64(0): raise PulseNotReceivedError() - self.t[i] = int(self.t[i] + ti - t0) - self.pmt0.count(now_mu()) # flush + self.t[i] = int32(int64(self.t[i]) + ti - t0) + self.ttl3.count(now_mu()) # flush