Created
January 28, 2019 15:29
-
-
Save dnadlinger/fb54dc976e18373ed34d4f2fc55f0ffe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from artiq.experiment import * | |
from artiq.coredevice.urukul import urukul_sta_smp_err, urukul_cfg | |
from artiq.coredevice.ad9910 import (_AD9910_REG_SYNC, _AD9910_REG_CFR1, | |
_AD9910_REG_CFR2) | |
import numpy as np | |
_MULTICHIP_SYNC_RECV = (1 << 27) + (1 << 26) # + (4<<28) | |
@portable | |
def multichip_sync_cfg(validation_delay, sync_recv_en, sync_gen_en, input_sync_delay): | |
return (validation_delay << 28) | (sync_recv_en << 27) | (sync_gen_en << 26) | ( | |
input_sync_delay << 3) | |
class MultichipSyncScan(EnvExperiment): | |
def build(self): | |
self.setattr_device("core") | |
self.setattr_device("ccb") | |
self.name = self.get_argument( | |
"Device", EnumerationValue(["urukul0", "urukul1", "rurukul0", "rurukul1"])) | |
self.syncsel = self.get_argument("Sync source", | |
EnumerationValue(["DDS", "FPGA"])) | |
def prepare(self): | |
self.cpld = self.get_device(self.name + "_cpld") | |
for i in range(4): | |
setattr(self, "ch{}".format(i), | |
self.get_device(self.name + "_ch{}".format(i))) | |
self.dds_sync = self.get_device("ttlclk_" + self.name + "_sync") | |
def issue_applets(self): | |
self.ccb.issue( | |
"create_applet", | |
"Sync error", | |
"${python} -m oxart.applets.plot_xy_fit " | |
"data.dds.errors --x data.dds.ts --ylabel \"Sync errors\" " | |
"--grids", | |
group="dds") | |
@kernel | |
def set_sync_recv_delay(self, ch, t): | |
delay(10 * us) | |
r = ch.read32(0xa) | |
r &= (~0xff) | |
r |= ((t & 0x1f) << 3) | |
delay(20 * us) | |
ch.write32(0xa, r) | |
delay(1 * us) | |
self.cpld.io_update.pulse(10 * ns) | |
@kernel | |
def resync(self, chobj): | |
delay(20 * us) | |
r = chobj.read32(_AD9910_REG_CFR2) | |
delay(50 * us) | |
r |= np.int32(1 << 5) # disable validation | |
chobj.write32(_AD9910_REG_CFR2, r) | |
self.cpld.io_update.pulse(10 * ns) | |
r &= np.int32(~(1 << 5)) # reenable validation | |
delay(50 * us) | |
chobj.write32(_AD9910_REG_CFR2, r) | |
delay(10 * us) | |
self.cpld.io_update.pulse(10 * ns) | |
@kernel | |
def sync_status(self, ch): | |
delay(15 * us) | |
s = urukul_sta_smp_err(self.cpld.sta_read()) | |
return 0 != s & (1 << ch) | |
def run(self): | |
self.issue_applets() | |
self.ts = [] | |
self.errors = [] | |
self.N = 1000 | |
sync_sel = 0 if self.syncsel == "FPGA" else 1 | |
self.cpld.cfg_reg = urukul_cfg( | |
rf_sw=0, | |
led=0, | |
profile=0, | |
io_update=0, | |
mask_nu=0, | |
clk_sel=0, | |
sync_sel=sync_sel, | |
rst=0, | |
io_rst=0) | |
self.krun() | |
@kernel | |
def krun(self): | |
self.core.reset() | |
delay(1 * ms) | |
tn = now_mu() | |
tn &= ~0xf | |
at_mu(tn) | |
self.dds_sync.set(125e6 / 2) | |
self.cpld.init() | |
self.ch0.init() | |
self.ch1.init() | |
self.ch2.init() | |
self.ch3.init() | |
self.ch0.set(100 * MHz, amplitude=0.) | |
self.ch0.sw.on() | |
self.ch0.set_att(0.) | |
# delay(10 *us) | |
self.ch1.set(100 * MHz, amplitude=0.) | |
self.ch1.sw.on() | |
self.ch1.set_att(0.) | |
# delay(10*us) | |
self.ch2.set(100 * MHz, amplitude=0.) | |
self.ch2.sw.on() | |
self.ch2.set_att(0.) | |
# delay(10*us) | |
self.ch3.set(100 * MHz, amplitude=0.) | |
self.ch3.sw.on() | |
self.ch3.set_att(0.) | |
# delay(10*us) | |
self.ch0.write32(_AD9910_REG_SYNC, multichip_sync_cfg(0, 1, 1, 0)) | |
delay(1 * us) | |
self.ch1.write32(_AD9910_REG_SYNC, multichip_sync_cfg(0, 1, 0, 0)) | |
delay(1 * us) | |
self.ch2.write32(_AD9910_REG_SYNC, multichip_sync_cfg(0, 1, 0, 0)) | |
delay(1 * us) | |
self.ch3.write32(_AD9910_REG_SYNC, multichip_sync_cfg(0, 1, 0, 0)) | |
delay(1 * us) | |
self.cpld.io_update.pulse(10 * ns) | |
for t in range(32): | |
self.core.break_realtime() | |
self.set_sync_recv_delay(self.ch0, t) | |
self.set_sync_recv_delay(self.ch1, t) | |
self.set_sync_recv_delay(self.ch2, t) | |
self.set_sync_recv_delay(self.ch3, t) | |
errs = [0] * 4 | |
for i in range(self.N): | |
self.resync(self.ch0) | |
self.resync(self.ch1) | |
self.resync(self.ch2) | |
self.resync(self.ch3) | |
for ch in range(4): | |
if self.sync_status(ch): | |
errs[ch] += 1 | |
self.report(t, errs) | |
def report(self, delay, ns): | |
print("{}\t{}".format(delay, ns)) | |
self.ts.append(delay) | |
self.errors.append(ns[0]) | |
self.set_dataset("data.dds.ts", self.ts, broadcast=True) | |
self.set_dataset("data.dds.errors", self.errors, broadcast=True) | |
class AutotuneDelays(EnvExperiment): | |
def build(self): | |
self.setattr_device("core") | |
self.setattr_device("ccb") | |
self.name = self.get_argument( | |
"Device", EnumerationValue(["urukul0", "urukul1", "rurukul0", "rurukul1"])) | |
def prepare(self): | |
self.cpld = self.get_device(self.name + "_cpld") | |
self.channels = [ | |
self.get_device(self.name + "_ch{}".format(i)) for i in range(4) | |
] | |
@kernel | |
def run(self): | |
self.core.reset() | |
self.core.break_realtime() | |
self.cpld.init() | |
for i in range(len(self.channels)): | |
ch = self.channels[i] | |
print() | |
print("Channel", i) | |
print("---") | |
self.core.break_realtime() | |
print("msync (delay, window):", ch.tune_sync_delay(15)) | |
self.core.break_realtime() | |
print("io_update_delay:", ch.tune_io_update_delay()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment