diff --git a/artiq/coredevice/sawg.py b/artiq/coredevice/sawg.py index f7897f212..647e30516 100644 --- a/artiq/coredevice/sawg.py +++ b/artiq/coredevice/sawg.py @@ -62,44 +62,36 @@ class Spline: rtio_output_list(now_mu(), self.channel, 0, value) @portable(flags={"fast-math"}) - def pack_coeff_mu(self, coeff) -> TList(TInt32): - n = len(coeff) - width = n*self.width + (n - 1)*n//2*self.time_width - packed = [int32(0)] * ((width + 31)//32) + def pack_coeff_mu(self, coeff, packed): pos = 0 - for i in range(n): + for i in range(len(coeff)): wi = self.width + i*self.time_width ci = coeff[i] - while wi: + while wi != 0: j = pos//32 used = pos - 32*j avail = 32 - used if avail > wi: avail = wi - packed[j] |= (ci & ((1 << avail) - 1)) << used + packed[j] |= int32(ci & ((1 << avail) - 1)) << used ci >>= avail wi -= avail pos += avail - return packed @portable(flags={"fast-math"}) - def coeff_to_mu(self, coeff) -> TList(TInt32): - n = len(coeff) - coeff64 = [int64(0)] * n - for i in range(n): + def coeff_to_mu(self, coeff, coeff64): + for i in range(len(coeff)): vi = coeff[i] * self.scale for j in range(i): vi *= self.time_scale ci = int(round(vi)) coeff64[i] = ci # artiq.wavesynth.coefficients.discrete_compensate: - continue if i == 2: coeff64[1] += ci >> (self.time_width + 1) elif i == 3: coeff64[2] += ci >> self.time_width coeff64[1] += (ci // 3) >> (2*self.time_width + 1) - return self.pack_coeff_mu(coeff64) @kernel def set_list(self, value): @@ -108,7 +100,13 @@ class Spline: :param value: List of floating point spline knot coefficients, lowest order (constant) coefficient first. """ - self.set_list_mu(self.coeff_to_mu(value)) + n = len(value) + width = n*self.width + (n - 1)*n//2*self.time_width + coeff64 = [int64(0)] * n + packed = [int32(0)] * ((width + 31)//32) + self.coeff_to_mu(value, coeff64) + self.pack_coeff_mu(coeff64, packed) + self.set_list_mu(packed) @kernel(flags={"fast-math"}) def smooth(self, start: TFloat, stop: TFloat, duration: TFloat, diff --git a/artiq/test/gateware/test_sawg_fe.py b/artiq/test/gateware/test_sawg_fe.py index a93f95daa..21230c97f 100644 --- a/artiq/test/gateware/test_sawg_fe.py +++ b/artiq/test/gateware/test_sawg_fe.py @@ -104,12 +104,18 @@ class SAWGTest(unittest.TestCase): def test_coeff(self): import struct - for v in [-.1], [.1, -.01], [.1, .01, -.00001], \ - [.1, .01, .00001, -.000000001]: + # these get discrete_compensate + # [.1, .01, -.00001], [.1, .01, .00001, -.000000001] + for v in [-.1], [.1, -.01]: ch = self.driver.offset - p = ch.coeff_to_mu(v) + q = [0] * len(v) + ch.coeff_to_mu(v, q) + n = len(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)] p0 = [struct.pack("<" + "_bhiiqqqq"[(w + i*t)//8], vi @@ -135,19 +141,28 @@ class SAWGTest(unittest.TestCase): self.assertEqual(out[2*i], v) self.assertEqual(out[2*i+1], v) - def test_pack(self): + def pack(self, v): + n = len(v) ch = self.driver.offset - self.assertEqual(ch.pack_coeff_mu([1]), [1]) - self.assertEqual(ch.pack_coeff_mu([1, 1 << 16]), [1, 1]) - self.assertEqual(ch.pack_coeff_mu([1, 1 << 32]), [1, 0]) - self.assertEqual(ch.pack_coeff_mu([0x1234, 0xa5a5a5a5]), + 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]), [0xa5a51234, 0xa5a5]) - self.assertEqual(ch.pack_coeff_mu([1, 2, 3, 4]), + self.assertEqual(self.pack([1, 2, 3, 4]), [0x20001, 0x30000, 0, 4, 0]) - self.assertEqual(ch.pack_coeff_mu([-1, -2, -3, -4]), + self.assertEqual(self.pack([-1, -2, -3, -4]), [0xfffeffff, 0xfffdffff, 0xffffffff, 0xfffffffc, 0xffffffff]) - self.assertEqual(ch.pack_coeff_mu([0, -1, 0, -1]), + self.assertEqual(self.pack([0, -1, 0, -1]), [0xffff0000, 0x0000ffff, 0, 0xffffffff, 0xffffffff]) @@ -171,3 +186,6 @@ class SAWGTest(unittest.TestCase): ch.set(.2) delay_mu(1*8) out = self.run_channel(self.rtio_manager.outputs) + # import matplotlib.pyplot as plt + # plt.plot(out) + # plt.show()