From ed6d1e73ccc62e0429ecc78571c5cd4ff80a90bf Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Tue, 29 Nov 2016 23:16:32 +0100 Subject: [PATCH] sawg: cleanup --- artiq/coredevice/sawg.py | 60 ++++++++++++++++++----------- artiq/test/gateware/test_sawg_fe.py | 54 ++++++++++---------------- 2 files changed, 59 insertions(+), 55 deletions(-) diff --git a/artiq/coredevice/sawg.py b/artiq/coredevice/sawg.py index 8bfe4edf9..b508b6fcd 100644 --- a/artiq/coredevice/sawg.py +++ b/artiq/coredevice/sawg.py @@ -1,7 +1,7 @@ from numpy import int32, int64 from artiq.language.core import kernel, now_mu, portable, delay from artiq.coredevice.rtio import rtio_output, rtio_output_wide -from artiq.language.types import TInt32, TInt64, TFloat, TList +from artiq.language.types import TInt32, TInt64, TFloat class Spline: @@ -44,18 +44,18 @@ class Spline: """ rtio_output(now_mu(), self.channel, 0, self.to_mu(value)) - @kernel + @kernel(flags={"fast-math"}) def set64(self, value: TFloat): """Set spline value. :param value: Spline value relative to full-scale. """ - v = self.to_mu64(value) - l = [int32(v), int32(v >> 32)] + l = [int32(0)] * 2 + self.pack_coeff_mu([self.to_mu64(value)], l) rtio_output_wide(now_mu(), self.channel, 0, l) @kernel - def set_coeff_mu(self, value): + def set_coeff_mu(self, value): # TList(TInt32) """Set spline raw values. :param value: Spline packed raw values. @@ -63,7 +63,7 @@ class Spline: rtio_output_wide(now_mu(), self.channel, 0, value) @portable(flags={"fast-math"}) - def pack_coeff_mu(self, coeff, packed): + def pack_coeff_mu(self, coeff, packed): # TList(TInt64), TList(TInt32) pos = 0 for i in range(len(coeff)): wi = self.width + i*self.time_width @@ -74,13 +74,16 @@ class Spline: avail = 32 - used if avail > wi: avail = wi - packed[j] |= int32(ci & ((1 << avail) - 1)) << used + cij = int32(ci) + if avail != 32: + cij &= (1 << avail) - 1 + packed[j] |= cij << used ci >>= avail wi -= avail pos += avail @portable(flags={"fast-math"}) - def coeff_to_mu(self, coeff, coeff64): + def coeff_to_mu(self, coeff, coeff64): # TList(TFloat), TList(TInt64) for i in range(len(coeff)): vi = coeff[i] * self.scale for j in range(i): @@ -94,18 +97,31 @@ class Spline: coeff64[2] += ci >> self.time_width coeff64[1] += ci // 6 >> 2*self.time_width - @kernel - def set_coeff(self, value): + def coeff_as_packed_mu(self, coeff64): + n = len(coeff64) + width = n*self.width + (n - 1)*n//2*self.time_width + packed = [int32(0)] * ((width + 31)//32) + self.pack_coeff_mu(coeff64, packed) + return packed + + def coeff_as_packed(self, coeff): + coeff64 = [int64(0)] * len(coeff) + self.coeff_to_mu(coeff, coeff64) + return self.coeff_as_packed_mu(coeff64) + + @kernel(flags={"fast-math"}) + def set_coeff(self, coeff): # TList(TFloat) """Set spline coefficients. :param value: List of floating point spline knot coefficients, - lowest order (constant) coefficient first. + lowest order (constant) coefficient first. Units are the + unit of this spline's value times increasing powers of 1/s. """ - n = len(value) - width = n*self.width + (n - 1)*n//2*self.time_width + n = len(coeff) coeff64 = [int64(0)] * n + self.coeff_to_mu(coeff, coeff64) + width = n*self.width + (n - 1)*n//2*self.time_width packed = [int32(0)] * ((width + 31)//32) - self.coeff_to_mu(value, coeff64) self.pack_coeff_mu(coeff64, packed) self.set_coeff_mu(packed) @@ -132,15 +148,15 @@ class Spline: and 3 are valid: step, linear, cubic. """ if order == 0: - delay(duration/2) + delay(duration/2.) self.set_coeff([stop]) - delay(duration/2) + delay(duration/2.) elif order == 1: self.set_coeff([start, (stop - start)/duration]) delay(duration) elif order == 3: - v2 = 6*(stop - start)/(duration*duration) - self.set_coeff([start, 0., v2, -2*v2/duration]) + v2 = 6.*(stop - start)/(duration*duration) + self.set_coeff([start, 0., v2, -2.*v2/duration]) delay(duration) else: raise ValueError("Invalid interpolation order. " @@ -153,14 +169,14 @@ class SAWG: oscillators = exp(2j*pi*(frequency0*t + phase0))*( amplitude1*exp(2j*pi*(frequency1*t + phase1)) + - amplitude2*exp(2j*pi*(frequency2*t + phase2)) + amplitude2*exp(2j*pi*(frequency2*t + phase2))) output = (offset + i_enable*Re(oscillators) + q_enable*Im(buddy_oscillators)) Where: - * offset, amplitude1, amplitude1: in units of full scale + * offset, amplitude1, amplitude2: in units of full scale * phase0, phase1, phase2: in units of turns * frequency0, frequency1, frequency2: in units of Hz @@ -184,13 +200,13 @@ class SAWG: self.amplitude1 = Spline(width, time_width, channel_base + 2, self.core, 1/(2*cordic_gain**2)) self.frequency1 = Spline(3*width, time_width, channel_base + 3, - self.core, 1/self.core.coarse_ref_period) + self.core, self.core.coarse_ref_period) self.phase1 = Spline(width, time_width, channel_base + 4, self.core, 1.) self.amplitude2 = Spline(width, time_width, channel_base + 5, self.core, 1/(2*cordic_gain**2)) self.frequency2 = Spline(3*width, time_width, channel_base + 6, - self.core, 1/self.core.coarse_ref_period) + self.core, self.core.coarse_ref_period) self.phase2 = Spline(width, time_width, channel_base + 7, self.core, 1.) self.frequency0 = Spline(2*width, time_width, channel_base + 8, diff --git a/artiq/test/gateware/test_sawg_fe.py b/artiq/test/gateware/test_sawg_fe.py index 8c90df3f6..5efbfa329 100644 --- a/artiq/test/gateware/test_sawg_fe.py +++ b/artiq/test/gateware/test_sawg_fe.py @@ -110,13 +110,9 @@ class SAWGTest(unittest.TestCase): # [.1, .01, -.00001], [.1, .01, .00001, -.000000001] for v in [-.1], [.1, -.01]: ch = self.driver.offset - q = [0] * len(v) - ch.coeff_to_mu(v, q) - n = len(v) + p = ch.coeff_as_packed(v) t = ch.time_width w = ch.width - p = [0] * ((n*w + (n - 1)*n//2*t + 31)//32) - ch.pack_coeff_mu(q, p) p = [_ & 0xffffffff for _ in p] p0 = [int(round(vi*ch.scale*ch.time_scale**i)) for i, vi in enumerate(v)] @@ -143,30 +139,19 @@ class SAWGTest(unittest.TestCase): self.assertEqual(out[i], [v, v]) self.assertEqual(out[-1], [0, 0]) - def pack(self, v): - n = len(v) - ch = self.driver.offset - t = ch.time_width - w = ch.width - p = [0] * ((n*w + (n - 1)*n//2*t + 31)//32) - ch.pack_coeff_mu(v, p) - p = [_ & 0xffffffff for _ in p] - return p - def test_pack(self): - self.assertEqual(self.pack([1]), [1]) - self.assertEqual(self.pack([1, 1 << 16]), [1, 1]) - self.assertEqual(self.pack([1, 1 << 32]), [1, 0]) - self.assertEqual(self.pack([0x1234, 0xa5a5a5a5]), + ch = self.driver.offset + self.assertEqual(ch.coeff_as_packed_mu([1]), [1]) + self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 16]), [1, 1]) + self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 32]), [1, 0]) + self.assertEqual(ch.coeff_as_packed_mu([0x1234, 0xa5a5a5a5]), [0xa5a51234, 0xa5a5]) - self.assertEqual(self.pack([1, 2, 3, 4]), + self.assertEqual(ch.coeff_as_packed_mu([1, 2, 3, 4]), [0x20001, 0x30000, 0, 4, 0]) - self.assertEqual(self.pack([-1, -2, -3, -4]), - [0xfffeffff, 0xfffdffff, 0xffffffff, - 0xfffffffc, 0xffffffff]) - self.assertEqual(self.pack([0, -1, 0, -1]), - [0xffff0000, 0x0000ffff, 0, - 0xffffffff, 0xffffffff]) + self.assertEqual(ch.coeff_as_packed_mu([-1, -2, -3, -4]), + [0xfffeffff, 0xfffdffff, -1, -4, -1]) + self.assertEqual(ch.coeff_as_packed_mu([0, -1, 0, -1]), + [0xffff0000, 0x0000ffff, 0, -1, -1]) def test_smooth_linear(self): ch = self.driver.offset @@ -190,11 +175,13 @@ class SAWGTest(unittest.TestCase): delay_mu(1) out = self.run_channel(self.rtio_manager.outputs) out = sum(out, []) - # import matplotlib.pyplot as plt - # plt.plot(out) - # plt.show() + if False: + import matplotlib.pyplot as plt + plt.plot(out) + plt.show() - @unittest.skip("needs sim.time.TimeManager tweak for timeline jumps") + # @unittest.skip("needs artiq.sim.time.TimeManager tweak for " + # "reverse timeline jumps") def test_demo_2tone(self): MHz = 1e-3 ns = 1. @@ -227,6 +214,7 @@ class SAWGTest(unittest.TestCase): out = self.run_channel(self.rtio_manager.outputs) out = sum(out, []) - # import matplotlib.pyplot as plt - # plt.plot(out) - # plt.show() + if True: + import matplotlib.pyplot as plt + plt.plot(out) + plt.show()