nsqdriver 0.3.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nsqdriver might be problematic. Click here for more details.

nsqdriver/__init__.py CHANGED
@@ -3,7 +3,7 @@ from .NS_QSYNC import Driver as QSYNCDriver
3
3
  from .NS_CST import Driver as CSTDriver
4
4
  from .compiler.ns_wave import InsChannel
5
5
 
6
- version_pack = (0, 3, 0)
6
+ version_pack = (0, 3, 1)
7
7
 
8
8
  __version__ = '.'.join(str(_) for _ in version_pack)
9
9
  __all__ = ['MCIDriver', 'QSYNCDriver', 'CSTDriver', 'InsChannel', '__version__']
nsqdriver/setup.py CHANGED
@@ -1,14 +1,9 @@
1
1
  from setuptools import setup
2
- from setuptools.extension import Extension
3
2
  from Cython.Build import cythonize
4
3
  import numpy as np
5
4
 
6
-
7
- extension = [Extension("*", ["nsqdriver/wrapper/*.py"], language='c++'),
8
- Extension("*", ["nsqdriver/*.py"], language='c++')]
9
-
10
5
  setup(
11
- name='nsqdriver',
12
- ext_modules=cythonize(extension, language_level=3),
6
+ name='compiler',
7
+ ext_modules=cythonize([r'nsqdriver/compiler/ns_wave.py', r'nsqdriver/compiler/py_wave_asm.py'], language_level=3),
13
8
  include_path=[np.get_include()]
14
9
  )
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.1
2
+ Name: nsqdriver
3
+ Version: 0.3.1
4
+ Summary: Naishu Q series quantum measurement and control equipment driver interface
5
+ Home-page: https://g2hoyqcmh4.feishu.cn/wiki/wikcnzvyMd82DLZUe2NsI6HxsFc
6
+ Author: Naishu Technology
7
+ Author-email: jilianyi@naishu.tech
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: numpy (>=1.18)
15
+ Requires-Dist: waveforms
16
+
17
+ ```
18
+ _ _ ____ ___ ____ _
19
+ | \ | | / ___| / _ \ | _ \ _ __ (_) __ __ ___ _ __
20
+ | \| | \___ \ | | | | | | | | | '__| | | \ \ / / / _ \ | '__|
21
+ | |\ | ___) | | |_| | | |_| | | | | | \ V / | __/ | |
22
+ |_| \_| |____/ \__\_\ |____/ |_| |_| \_/ \___| |_|
23
+ ```
24
+
25
+ [![Tests](https://github.com/mianyan-echo/UltraMCI/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/mianyan-echo/UltraMCI/)
26
+ ***
27
+
28
+ ### 简介
29
+ NSQDriver为一套耐数®量子测控系列设备的Python通用驱动接口。可使用Python作为编程语言,基于此驱动接口可以实现对本公司测控设备的控制,进而完成各种超导量子芯片的表征实验和高保真门操作。
30
+
31
+ ```
32
+ +------------------------+
33
+ | Python |
34
+ | +------------------+
35
+ | | NSQDriver |
36
+ +------------------------+
37
+ : : :
38
+ +---------- : -----+
39
+ : : :
40
+ V V V
41
+ +-----------+ +-----------+ +-----------+
42
+ | Device A | | Device B | | QSYNC |
43
+ +-----------+ +-----------+ +-----------+
44
+ ```
45
+
46
+ NSQDriver接口可用于统一控制耐数®生产的Q100、MC、QSYNC等一系列量子测控仪器,可详细控制每台仪器每个OUT、IN通道的播放与采集行为,以及查看设备的运行状态等。在一个多台测控设备组成的多量子比特测控系统中,可以有效的在软件层面实现对系统中每台设备的详细控制。
47
+
48
+ 耐数®量子测控系列设备详细信息参考: [耐数](http://naishu.tech)
49
+
50
+ ***
51
+ ### 快速开始
52
+ - 驱动接口的通用流程如下
53
+ ```python
54
+ from nsqdriver import MCIDriver, QSYNCDriver
55
+
56
+ # 实例化设备驱动接口
57
+ driver = MCIDriver('127.0.0.1')
58
+ qsync = QSYNCDriver('127.0.0.1')
59
+
60
+ # 连接设备
61
+ qsync.open()
62
+ driver.open()
63
+
64
+ # 初始化系统
65
+ qsync.sync_system()
66
+
67
+
68
+ # 相关参数,参数细节相关参考 8.可用参数列表
69
+ driver.set('Shot', 1024)
70
+ ```
71
+
72
+ - NSWave接口
73
+ - NSWave是一种对于耐数®参数化波形技术的控制接口,参数化波形将量子测控所需的各种门的编辑由主控计算机直接生成波形转化成了设备实时计算
74
+ - 提供了一套直观的时序编辑接口
75
+ ```python
76
+ from nsqdriver import InsChannel
77
+ import numpy as np
78
+
79
+ ch = InsChannel() # 生成参数化波形通道实例
80
+
81
+ frame_65e9 = ch.ins_frame(6.5e9) # 生成一个frame
82
+ frame_67e9 = ch.ins_frame(6.7e9) # 生成一个frame
83
+
84
+ gaussian = ch.evlp_gaussian(4500e-9) # 生成一个高斯包络
85
+ square = ch.evlp_square(2500e-9) # 生成一个方波包络
86
+
87
+ wave1 = gaussian * frame_67e9 # 生成一段高斯包络的波形
88
+ wave2 = square * frame_65e9 # 生成一段方波包络的波形
89
+
90
+ ch.ins_reset_frame('phase', frame_65e9)
91
+ ch.ins_reset_frame('phase', frame_67e9)
92
+ ch.wait_for_trigger() # 等待触发到来
93
+ # 循环播放200次 3μs延迟+ 7μs波形
94
+ with ch.ins_loop(times=200) as _loop:
95
+ _loop.play_zero(3000e-9)
96
+ _loop.inc_phase(frame_65e9, np.pi / 2)
97
+ _loop.play_wave(wave2)
98
+ _loop.play_wave(wave1)
99
+ ```
@@ -1,17 +1,17 @@
1
1
  nsqdriver/NS_CST.py,sha256=_QYCjg1YglIJ4YVmxvISqvy5rExWGlMhyrK9zYIRbRY,7877
2
2
  nsqdriver/NS_MCI.py,sha256=ZRf_waF7Q3VnClZnvjogfhVkqW7ltmwZaXXCRU8qA0o,19542
3
3
  nsqdriver/NS_QSYNC.py,sha256=68qFZ04KVXb0MSaeKIZVZYqR0UV_tkJYWz7KSz4Dvg0,23281
4
- nsqdriver/__init__.py,sha256=BMKtTehGZlv0CgT1vJAbyZW1KF670NZwQJ9wWQBYzC0,326
4
+ nsqdriver/__init__.py,sha256=BXs30hyT5ovY79xD1SYbTce9c1CPM7q0siC1EjyzGwk,326
5
5
  nsqdriver/common.py,sha256=IHfShqgNN3THbe7KD7ICdfFY7JKC_kQj0_KJk-449gQ,499
6
- nsqdriver/setup.py,sha256=4ajKQtY4hr2240f5sA81f66_92Yp_wG6gPM-zsOWq9M,390
6
+ nsqdriver/setup.py,sha256=qLy-jDmc3nxnXVoJo4g2cnTvFL3lOiYu_t-vaJ8Z_8o,269
7
7
  nsqdriver/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- nsqdriver/compiler/ns_wave.py,sha256=Z-O--9OtmLiILGx-4imSJuAcdgjP1PNknQlDrSo2CIw,15411
9
- nsqdriver/compiler/py_wave_asm.py,sha256=aXMr3CqMC0vDP4mtTdyVfnwpvlrE14hGgdthWAF5S6g,17407
8
+ nsqdriver/compiler/ns_wave.cpython-310-darwin.so,sha256=WBh_NOyU4e6G6xBitLFXLkkFvKqCn9ptf3cGTEkjEaE,410360
9
+ nsqdriver/compiler/py_wave_asm.cpython-310-darwin.so,sha256=noQ3HaHLl1NUsT29eU_XA3j5Nlp4_egB-nQqjYiy8p8,432200
10
10
  nsqdriver/wrapper/AWG_ADC.py,sha256=8K5xLEa_3CKnStWcoJeTj8ufEQfrx6o4l4XGNuOP3Ug,19211
11
11
  nsqdriver/wrapper/BD_NSMCI.py,sha256=SMnDbS6iXDiPBhoR9QVJB_lJXhIXRQIVLJRSBEihLzw,12245
12
12
  nsqdriver/wrapper/ND_NSMCI.py,sha256=gTyrDObhbggl35V_q-kpDoPsfttIEnDFc6f0-pk_P0k,6288
13
13
  nsqdriver/wrapper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- nsqdriver-0.3.0.dist-info/METADATA,sha256=htBmUOmmEPWvuvX1fmTGsoFlXiZPqysgxrwFnjDDwp0,497
15
- nsqdriver-0.3.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
16
- nsqdriver-0.3.0.dist-info/top_level.txt,sha256=o7EbQoFO6BoaG3KGbS9Lg_aRheZSY5KYzoYuI9vx-AI,10
17
- nsqdriver-0.3.0.dist-info/RECORD,,
14
+ nsqdriver-0.3.1.dist-info/METADATA,sha256=qGCBFfF-7sVIK42k9E5AqUPxEWrawBmI1fSMhoNDOJU,4091
15
+ nsqdriver-0.3.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
16
+ nsqdriver-0.3.1.dist-info/top_level.txt,sha256=o7EbQoFO6BoaG3KGbS9Lg_aRheZSY5KYzoYuI9vx-AI,10
17
+ nsqdriver-0.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,483 +0,0 @@
1
- import copy
2
- from typing import Union, List, Dict
3
- from itertools import chain, repeat
4
- from enum import IntEnum
5
- from collections import namedtuple
6
-
7
- import numpy as np
8
- import waveforms as wf
9
-
10
- from .py_wave_asm import *
11
-
12
-
13
- class QInsPlaceholder(NSQCommand):
14
- ...
15
-
16
-
17
- class Wave(GenTagMixin):
18
- Identity = namedtuple('Relation', ['frame', 'envelop'])
19
-
20
- class Tag(IntEnum):
21
- none = 0
22
- frame = 1
23
- envelope = 2
24
- signal = 3
25
-
26
- def __init__(self, ins_obj: "InstructionQ", ins_id: dict):
27
- cls = self.__class__
28
- self.instruction = ins_obj
29
- self.id = cls.Identity(**ins_id)
30
- if ins_id['frame'] != -1 and ins_id['envelop'] != -1:
31
- self.wtag = cls.Tag.signal
32
- elif ins_id['frame'] != -1:
33
- self.wtag = cls.Tag.envelope
34
- elif ins_id['envelop'] != -1:
35
- self.wtag = cls.Tag.frame
36
- else:
37
- self.wtag = cls.Tag.none
38
-
39
- def __repr__(self):
40
- return f'<{self.__class__}::{self.id}::{self.wtag}>'
41
-
42
-
43
- class Frame(Wave):
44
- def __init__(self, ins_obj: "InstructionQ", ins_id: int, freq: float):
45
- super().__init__(ins_obj, {'frame': ins_id, 'envelop': -1})
46
- self.tag = self.generate_tag
47
- self.freq = freq
48
-
49
- @property
50
- def freq(self):
51
- return self._freq
52
-
53
- @freq.setter
54
- def freq(self, value):
55
- self._freq = value
56
- self._ins = QInsFrame(freq=value, tag=self.tag)
57
-
58
- def __mul__(self, other: Wave):
59
- if isinstance(other, Envelope) or isinstance(other, Signal):
60
- if other.instruction is not self.instruction:
61
- raise ValueError(f'隶属于的instruction不同,不能直接相乘')
62
- res = Signal(self.instruction, {'frame': self.id.frame, 'envelop': other.id.envelop})
63
- res.frame = self
64
- res.envelope = other
65
- return res
66
- else:
67
- raise ValueError(f'{self.__class__}不能与{other.__class__}做乘法运算')
68
-
69
- def format(self):
70
- return self._ins
71
-
72
-
73
- class Envelope(Wave):
74
- def __init__(self, ins_obj: "InstructionQ", ins_id: int, content):
75
- super().__init__(ins_obj, {'frame': -1, 'envelop': ins_id})
76
- self.tag = self.generate_tag
77
- self.content = content
78
-
79
- @property
80
- def content(self):
81
- return self._content
82
-
83
- @content.setter
84
- def content(self, value):
85
- self._content = value
86
- self._ins = QInsEnvelop(envelop=self.content, tag=self.tag)
87
-
88
- def __mul__(self, other: Wave):
89
- if isinstance(other, Frame) or isinstance(other, Signal):
90
- if other.instruction is not self.instruction:
91
- raise ValueError(f'They belong to different instructions and cannot be directly multiplied')
92
- res = Signal(self.instruction, {'frame': other.id.frame, 'envelop': self.id.envelop})
93
- res.frame = other
94
- res.envelope = self
95
- return res
96
- else:
97
- raise ValueError(f'{self.__class__}不能与{other.__class__}做乘法运算')
98
-
99
- def format(self):
100
- return self._ins
101
-
102
-
103
- class Signal(Wave):
104
- def __init__(self, ins_obj: "InstructionQ", ins_id: dict):
105
- super().__init__(ins_obj, ins_id)
106
- self.frame = None
107
- self.envelope = None
108
-
109
-
110
- class InstructionQ(GenTagMixin):
111
- """!
112
- 包含各种具体的指令
113
- """
114
-
115
- def __init__(self, freqs=None, envelopes=None):
116
- """!
117
-
118
- @param freqs:
119
- @param envelopes:
120
- """
121
- if freqs is None:
122
- freqs = []
123
- if envelopes is None:
124
- envelopes = []
125
- self.i_set: "List[Union[NSQCommand, InstructionQ]]" = []
126
- self.f_set: "Dict[int, Frame]" = {}
127
- self.e_set: "Dict[int, Envelope]" = {}
128
- self.symbol_set: Dict[str, int] = {}
129
- self.symbol_idx = -1
130
- self.is_first_trig = True
131
- self.last_ins = None
132
-
133
- for i, f in enumerate(freqs):
134
- self.ins_frame(f)
135
- for i, e in enumerate(envelopes):
136
- self.ins_envelope(e)
137
-
138
- def __enter__(self):
139
- return self
140
-
141
- def __exit__(self, exc_type, exc_val, exc_tb):
142
- ...
143
-
144
- def clear(self):
145
- self.i_set.clear()
146
- self.symbol_set: Dict[str, int] = {}
147
- self.symbol_idx = -1
148
- self.is_first_trig = True
149
-
150
- @property
151
- def length(self):
152
- return len(self.i_set)
153
-
154
- def ins_frame(self, freq, idx=None) -> Frame:
155
- raise RuntimeError(f'Cannot create a new frame in the branch')
156
-
157
- def ins_envelope(self, envelope: "Union[np.ndarray, wf.Waveform, str]", idx=None) -> Envelope:
158
- raise RuntimeError(f'Cannot create a new envelope in the branch')
159
-
160
- def evlp_gaussian(self, width) -> Envelope:
161
- wave = wf.gaussian(width) >> (width/2)
162
- wave.start = 0
163
- wave.stop = width
164
- return self.ins_envelope(wave)
165
-
166
- def evlp_cospulse(self, width) -> Envelope:
167
- wave = wf.cosPulse(width) >> (width / 2)
168
- wave.start = 0
169
- wave.stop = width
170
- return self.ins_envelope(wave)
171
-
172
- def evlp_square(self, width) -> Envelope:
173
- wave = wf.square(width) >> (width / 2)
174
- wave.start = 0
175
- wave.stop = width
176
- return self.ins_envelope(wave)
177
-
178
- def _append_ins(self, cmd: "Union[NSQCommand, InstructionQ]"):
179
- self.last_ins = cmd
180
- self.i_set.append(cmd)
181
-
182
- def _map_var(self, var):
183
- if var in self.symbol_set:
184
- return self.symbol_set[var]
185
- self.symbol_idx += 1
186
- if self.symbol_idx >= 16:
187
- raise RuntimeError(f'Up to 16 variables can be configured')
188
- self.symbol_set[var] = self.symbol_idx
189
- return self.symbol_set[var]
190
-
191
- def wait_for_trigger(self):
192
- if not self.is_first_trig:
193
- self.wait()
194
- cmd = QInsWaitTrig(tag=self.generate_tag)
195
- self._append_ins(cmd)
196
- return cmd
197
-
198
- def ins_variable(self, reg: str, value: int):
199
- cmd = QInsMov(self._map_var(reg), value, type='=', tag=self.generate_tag)
200
- self._append_ins(cmd)
201
- return cmd
202
-
203
- def ins_add(self, reg: str, value: int):
204
- cmd = QInsMov(self._map_var(reg), value, type='+', tag=self.generate_tag)
205
- self._append_ins(cmd)
206
- return cmd
207
-
208
- def ins_reset_frame(self, flag, frame=''):
209
- cmd = QInsResetF(flag, frame, tag=self.generate_tag)
210
- self._append_ins(cmd)
211
- return cmd
212
-
213
- def inc_phase(self, frame, phase):
214
- cmd = QInsIncPhase(phase, frame.tag, tag=self.generate_tag)
215
- self._append_ins(cmd)
216
- return cmd
217
-
218
- def play_wave(self, wave: Signal, amp=1, freq=0, phase=0):
219
- if not isinstance(wave, Signal):
220
- raise RuntimeError(f'The parameter wave should be Signal, not {type(wave)}')
221
- cmd = QInsPlayWave(wave.frame.tag, wave.envelope.tag, amp, freq, phase, tag=self.generate_tag)
222
- self._append_ins(cmd)
223
- return cmd
224
-
225
- def play_zero(self, width):
226
- cmd = QInsPlayZero(width, tag=self.generate_tag)
227
- self._append_ins(cmd)
228
- return cmd
229
-
230
- def wait(self):
231
- cmd = QInsWait(tag=self.generate_tag)
232
- self._append_ins(cmd)
233
- return cmd
234
-
235
- def end(self):
236
- cmd = QInsEnd(tag=self.generate_tag)
237
- self._append_ins(cmd)
238
- return cmd
239
-
240
- def capture(self, width, delay=0):
241
- cmd = QInsCapture(width=width, probe_delay=delay, tag=self.generate_tag)
242
- self._append_ins(cmd)
243
- return cmd
244
-
245
- def _compile(self) -> "List[NSQCommand]":
246
- res = []
247
- for ins in self.i_set:
248
- if isinstance(ins, InstructionQ):
249
- res.extend(ins._compile())
250
- else:
251
- res.append(copy.copy(ins))
252
- return res
253
-
254
- def compile(self) -> "List[NSQCommand]":
255
- queue = []
256
- for idx in sorted(self.f_set.keys()):
257
- ins = self.f_set[idx]
258
- queue.append(ins.format())
259
- for idx in sorted(self.e_set.keys()):
260
- ins = self.e_set[idx]
261
- queue.append(ins.format())
262
-
263
- queue.extend(self._compile())
264
- # 向指令队列中添加End指令
265
- if not isinstance(queue[-1], QInsEnd):
266
- queue.append(self.end())
267
-
268
- res = []
269
- for idx, ins in enumerate(queue):
270
- if isinstance(ins, QInsPlaceholder):
271
- f_tag = ins.tag
272
- t_tag = queue[idx+1].tag
273
- for _ins in queue:
274
- if getattr(_ins, 'target', '') == f_tag:
275
- _ins.target = t_tag
276
- continue
277
- res.append(ins)
278
- return res
279
-
280
- def lookup(self):
281
- import json
282
- ins_list = [str(ins) for ins in self.compile()]
283
- print(json.dumps(ins_list, indent=4))
284
-
285
-
286
- class InsChannel(InstructionQ):
287
- def __init__(self, freqs=None, envelopes=None):
288
- super(InsChannel, self).__init__(freqs, envelopes)
289
- self.if_stack: "List[InsIF]" = []
290
- self.looping = False
291
-
292
- def clear(self):
293
- super().clear()
294
- self.looping = False
295
-
296
- def ins_frame(self, freq, idx=None) -> Frame:
297
- if idx is None:
298
- idx = sorted(self.f_set)[-1]+1 if len(self.f_set) != 0 else 0
299
- if not isinstance(idx, int):
300
- raise ValueError(f'frame的idx应为整数,而不是{type(idx)}')
301
- frame = Frame(self, idx, freq)
302
- self.f_set[idx] = frame
303
- return frame
304
-
305
- def ins_envelope(self, envelope: "Union[np.ndarray, wf.Waveform, str]", idx=None) -> Envelope:
306
- if idx is None:
307
- idx = sorted(self.e_set)[-1] + 1 if len(self.e_set) != 0 else 0
308
- if not isinstance(idx, int):
309
- raise ValueError(f'envelop的idx应为整数,而不是{type(idx)}')
310
- obj = Envelope(self, idx, envelope)
311
- self.e_set[idx] = obj
312
- return obj
313
-
314
- def ins_if(self, formula) -> "InsIF":
315
- channel = self if self.__class__ is InsChannel else self.channel
316
- if_ins = InsIF.from_channel(channel)
317
- if_ins.formula = formula
318
- self._append_ins(if_ins)
319
- self.if_stack.append(if_ins)
320
- return if_ins
321
-
322
- def ins_else(self) -> "InsElse":
323
- # if与else之间不能间隔其它指令
324
- if not isinstance(self.last_ins, InsIF):
325
- raise RuntimeError(f'The last call of ins_else must be ins_if, not {type(self.last_ins)}')
326
- # 不能没有if直接调用else
327
- if len(self.if_stack) == 0:
328
- raise RuntimeError(f'Please call if before calling else')
329
- channel = self if self.__class__ is InsChannel else self.channel
330
- _if = self.if_stack.pop()
331
- _else = InsElse.from_channel(channel)
332
- _else._if = _if
333
- _if.ins_else = _else
334
- return _else
335
-
336
- def ins_loop(self, times) -> "InsLoop":
337
- if self.looping:
338
- raise RuntimeError(f'The current object is already in the loop')
339
- channel = self if self.__class__ is InsChannel else self.channel
340
- loop_ins = InsLoop.from_channel(channel)
341
- loop_ins.times = times
342
- self._append_ins(loop_ins)
343
- return loop_ins
344
-
345
-
346
- class InsIF(InsChannel):
347
- ch_judge_name = {f'FREQ_{i}': 1<<i for i in range(6)}
348
-
349
- def __init__(self, freqs=None, envelopes=None):
350
- """!
351
-
352
- @param freqs:
353
- @param envelopes:
354
- """
355
- super().__init__(freqs, envelopes)
356
- self.channel: "InsChannel" = None
357
- self.key_ins = None
358
- self.ins_else = None
359
-
360
- @classmethod
361
- def from_channel(cls, channel):
362
- self = cls()
363
- self.channel = channel
364
- return self
365
-
366
- @property
367
- def formula(self):
368
- raise RuntimeError(f'{self.__class__.__name__}.formula is a static property')
369
-
370
- @formula.setter
371
- def formula(self, formula: str):
372
- formula = formula.replace(' ', '')
373
- ast = formula.split('==')
374
- if len(ast) != 2:
375
- raise RuntimeError(f'The format of formula should be [name] == [value]')
376
- name, value = ast
377
- if name in self.channel.symbol_set:
378
- self.key_ins = QInsJumpWithReg(self.channel.symbol_set[name], int(value), None, tag=self.generate_tag)
379
- elif name in self.ch_judge_name:
380
- self.key_ins = QInsJumpWithJudge(int(value), self.ch_judge_name[name], None, tag=self.generate_tag)
381
- else:
382
- raise RuntimeError(f'The specified variable {name} does not exist')
383
-
384
- def _compile(self) -> "List[NSQCommand]":
385
- """!
386
- 递归生成分支结构,支持结构嵌套
387
- @return:
388
- """
389
- res = []
390
- if_group = super()._compile()
391
- else_group = self.ins_else._compile() if isinstance(self.ins_else, InsElse) else []
392
- while len(else_group) < 3:
393
- else_group.append(QInsWait(tag=self.generate_tag))
394
- if_group.append(QInsPlaceholder(tag=self.generate_tag))
395
- jump = QInsJump(None, tag=self.generate_tag)
396
- self.key_ins.target = if_group[0].tag
397
- jump.target = if_group[-1].tag
398
-
399
- res.append(self.key_ins)
400
- res.extend(else_group)
401
- res.append(jump)
402
- res.extend(if_group)
403
- return res
404
-
405
- def capture(self, width, delay=0):
406
- raise RuntimeError(f'Capture is not allowed to call in a branch structure')
407
-
408
-
409
- class InsElse(InsChannel):
410
- def __init__(self, freqs=None, envelopes=None):
411
- """!
412
-
413
- @param freqs:
414
- @param envelopes:
415
- """
416
- super().__init__(freqs, envelopes)
417
- self.channel = None
418
- self._if = None
419
-
420
- @classmethod
421
- def from_channel(cls, channel):
422
- self = cls()
423
- self.channel = channel
424
- return self
425
-
426
- def capture(self, width, delay=0):
427
- raise RuntimeError(f'Capture is not allowed to call in a branch structure')
428
-
429
-
430
- class InsLoop(InsChannel):
431
- def __init__(self, freqs=None, envelopes=None):
432
- """!
433
-
434
- @param freqs:
435
- @param envelopes:
436
- """
437
- super().__init__(freqs, envelopes)
438
- self.channel: "InsChannel" = None
439
- self.times = None
440
- self.var = self.generate_tag
441
-
442
- def __enter__(self):
443
- self.channel.looping = True
444
- return self
445
-
446
- def __exit__(self, exc_type, exc_val, exc_tb):
447
- self.looping = False
448
-
449
- @classmethod
450
- def from_channel(cls, channel):
451
- self = cls()
452
- self.channel = channel
453
- return self
454
-
455
- def capture(self, width, delay=0):
456
- raise RuntimeError(f'Calling capture in a loop construct is not allowed')
457
-
458
- def _compile(self) -> "List[NSQCommand]":
459
- body = super()._compile()
460
- res = []
461
- set_cmd = QInsMov(self.channel._map_var(self.var), 0, type='=', tag=self.generate_tag)
462
- body.append(QInsMov(self.channel._map_var(self.var), 1, type='+', tag=self.generate_tag))
463
- placeholder = QInsPlaceholder(tag=self.generate_tag)
464
- jump = [
465
- QInsJumpWithReg(self.channel._map_var(self.var), self.times, placeholder.tag, tag=self.generate_tag),
466
- QInsWait(tag=self.generate_tag),
467
- QInsWait(tag=self.generate_tag),
468
- QInsJump(body[0].tag, tag=self.generate_tag),
469
- placeholder
470
- ]
471
- res.append(set_cmd)
472
- res.extend(body)
473
- res.extend(jump)
474
- return res
475
-
476
- # def _compile(self) -> "List[NSQCommand]":
477
- # ins_list = super()._compile()
478
- # res = []
479
- # for ins in chain.from_iterable(repeat(ins_list, self.times)):
480
- # _ins: "NSQCommand" = copy.copy(ins)
481
- # _ins.tag = self.generate_tag
482
- # res.append(_ins)
483
- # return res
@@ -1,538 +0,0 @@
1
- import struct
2
- import copy
3
- import uuid
4
- from typing import Union, List, Tuple, Dict
5
- from enum import IntEnum
6
- from dataclasses import dataclass, field
7
- from itertools import chain
8
- from collections import ChainMap
9
-
10
- import numpy as np
11
- import waveforms as wf
12
-
13
- __all__ = [
14
- 'AssemblyError', 'GenTagMixin', 'Assembler', 'NSQCommand',
15
- 'QInsWait', 'QInsWaitTrig', 'QInsEnd', 'QInsFrame', 'QInsEnvelop',
16
- 'QInsJumpWithJudge', 'QInsJump', 'QInsJumpWithReg', 'QInsCapture',
17
- 'QInsMov', 'QInsIncPhase', 'QInsPlayZero', 'QInsPlayWave', 'QInsResetF',
18
- ]
19
-
20
- global_config = {
21
- 'play_zero_step': 4e-9,
22
- 'OUTSrate': 8e9,
23
- 'envelope_dtype': np.int16, # 描述包络每个点的数据类型
24
- 'envelope_step': 64, # 包络步进粒度,单位为bytes
25
- 'envelope_quant': 16383, # 包络量化范围
26
- 'envelope_cache': 204800, # 包络缓存大小,单位bytes
27
- 'envelope_head': np.array([2, 0, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=np.int16), # 包络更新包头
28
- }
29
-
30
-
31
- class AssemblyError(RuntimeError):
32
- ...
33
-
34
-
35
- class GenTagMixin:
36
- @property
37
- def generate_tag(self):
38
- return uuid.uuid4().hex[:10]
39
-
40
-
41
- @dataclass
42
- class NSQCommand:
43
- """!
44
- 所有参数化波形指令队列的基类
45
- """
46
- tag: str = field(kw_only=True)
47
-
48
- def _check_attr(self):
49
- ...
50
-
51
- def __bytes__(self):
52
- self._check_attr()
53
- cmd = self._pack_cmd()
54
- return self.list2bytes(cmd)
55
-
56
- def _pack_cmd(self) -> list:
57
- return [0x00, 0, 0, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
58
-
59
- @property
60
- def overhead(self):
61
- return 16e-9
62
-
63
- @staticmethod
64
- def list2bytes(cmd: list):
65
- cmd += [0x00] * 8
66
- cmd_raw = struct.pack('=BBIIHHHII' + 'B' * 8, *cmd)
67
- return cmd_raw
68
-
69
- @staticmethod
70
- def frequency_normalization32(freq) -> np.uint32:
71
- return np.uint32(round(freq / global_config['OUTSrate'] * (1 << 32)))
72
-
73
- @staticmethod
74
- def phase_normalization32(phase) -> np.uint32:
75
- return np.uint32(round(np.fmod(np.fmod(phase / np.pi / 2, 1) + 1, 1) * (1 << 32)))
76
-
77
-
78
- @dataclass
79
- class _ProbeCommand:
80
- tag: str = field(kw_only=True)
81
-
82
- def _check_attr(self):
83
- ...
84
-
85
- def __bytes__(self):
86
- self._check_attr()
87
- cmd = self._pack_cmd()
88
- return self.list2bytes(cmd)
89
-
90
- def _pack_cmd(self) -> list:
91
- return [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000]
92
-
93
- @property
94
- def overhead(self):
95
- return 16e-9
96
-
97
- @staticmethod
98
- def list2bytes(cmd: list):
99
- cmd_raw = struct.pack('=HHHHHHHH', *cmd[::-1])
100
- return cmd_raw
101
-
102
-
103
- @dataclass
104
- class QInsEnvelop(NSQCommand):
105
- envelop: Union[np.ndarray, wf.Waveform]
106
-
107
- def __post_init__(self):
108
- self.envelop_slice = slice(0, None, 1)
109
-
110
- def __bytes__(self):
111
- if isinstance(self.envelop, wf.Waveform):
112
- if self.envelop.start is None or self.envelop.stop is None:
113
- raise AssemblyError(f'When the type of {self.__class__.__name__}.envelop is wf.Waveform, '
114
- f'it must have start and stop attributes')
115
- wave = self.envelop.sample(global_config['OUTSrate'])
116
- elif isinstance(self.envelop, np.ndarray):
117
- wave = self.envelop
118
- else:
119
- raise AssemblyError(f'The type of {self.__class__.__name__}.envelop must be one of np.ndarray or wf.Waveform')
120
- wave *= global_config['envelope_quant']
121
- return wave.astype(global_config['envelope_dtype']).tobytes()
122
-
123
-
124
- @dataclass
125
- class QInsFrame(NSQCommand):
126
- freq: float
127
-
128
- def __post_init__(self):
129
- self.frame_idx = 0
130
-
131
- def _pack_cmd(self) -> list:
132
- return [0x11, self.frame_idx * 4 + 0, self.frequency_normalization32(self.freq),
133
- 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
134
-
135
-
136
- @dataclass
137
- class QInsResetF(NSQCommand):
138
- type: str
139
- frame: str = ''
140
-
141
- def __post_init__(self):
142
- self.frame_idx = 0
143
- self.type2head = {'all': 0x51, 'single': 0x41, 'phase': 0x31}
144
-
145
- def _pack_cmd(self) -> list:
146
- head = self.type2head.get(self.type.lower(), None)
147
- if head is None:
148
- raise AssemblyError(f'{self.__class__.__name__}.type can only be one of {self.type2head.keys()}')
149
- return [head, self.frame_idx * 4, 0, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
150
-
151
-
152
- @dataclass
153
- class QInsMov(NSQCommand):
154
- reg: int
155
- value: int
156
- type: str = '='
157
-
158
- def __post_init__(self):
159
- self.type2head = {'=': 0x38, '+': 0x48}
160
-
161
- def _pack_cmd(self) -> list:
162
- head = self.type2head.get(self.type, None)
163
- if head is None:
164
- raise AssemblyError(f'{self.__class__.__name__}.type can only be one of {self.type2head.keys()}')
165
- return [head, self.reg, self.value, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
166
-
167
-
168
- @dataclass
169
- class QInsWaitTrig(NSQCommand):
170
- def _pack_cmd(self) -> list:
171
- return [0xF4, 0, 0, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
172
-
173
-
174
- @dataclass
175
- class QInsIncPhase(NSQCommand):
176
- phase: float
177
- frame: str
178
-
179
- def __post_init__(self):
180
- self.frame_idx = 0
181
-
182
- def _pack_cmd(self) -> list:
183
- return [0x21, self.frame_idx * 4 + 1, self.phase_normalization32(self.phase),
184
- 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
185
-
186
-
187
- @dataclass
188
- class QInsPlayZero(NSQCommand):
189
- width: float
190
-
191
- @property
192
- def overhead(self):
193
- return self.width
194
-
195
- def _pack_cmd(self) -> list:
196
- frames = round(self.width / global_config['play_zero_step'])
197
- return [0x44, 0, 0, frames, 0, 0x0000, 0x0000, 0, 0]
198
-
199
-
200
- @dataclass
201
- class QInsPlayWave(NSQCommand):
202
- frame: str
203
- envelop: str
204
- amp: float
205
- attach_freq: float
206
- attach_phase: float
207
-
208
- @property
209
- def overhead(self):
210
- return self.envelop_slice.step/global_config['OUTSrate']
211
-
212
- def __post_init__(self):
213
- self.frame_idx = 0
214
- self.envelop_slice = slice(0, None, 1)
215
-
216
- def _pack_cmd(self) -> list:
217
- return [
218
- 0x04, self.frame_idx * 4,
219
- np.uint32(self.envelop_slice.start / global_config['envelope_step']),
220
- np.uint32(self.envelop_slice.step / global_config['envelope_step']),
221
- np.int32(self.amp * (1 << 15)), 0x0000, 0x0000,
222
- self.frequency_normalization32(self.attach_freq),
223
- self.phase_normalization32(self.attach_phase)
224
- ]
225
-
226
-
227
- @dataclass
228
- class QInsWait(NSQCommand):
229
- def _pack_cmd(self) -> list:
230
- return [0x00, 0, 0, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
231
-
232
-
233
- @dataclass
234
- class QInsJump(NSQCommand):
235
- target: str
236
-
237
- def __post_init__(self):
238
- self.ins_idx = 0
239
-
240
- def _pack_cmd(self) -> list:
241
- return [0x18, 0, 0, self.ins_idx, 0, 0x0000, 0x0000, 0, 0]
242
-
243
-
244
- @dataclass
245
- class QInsJumpWithReg(NSQCommand):
246
- reg: int
247
- value: int
248
- target: str
249
-
250
- def __post_init__(self):
251
- self.ins_idx = 0
252
-
253
- def _pack_cmd(self) -> list:
254
- return [0x28, self.reg, self.value, self.ins_idx, 0, 0x0000, 0x0000, 0, 0]
255
-
256
-
257
- @dataclass
258
- class QInsJumpWithJudge(NSQCommand):
259
- value: int
260
- mask: int
261
- target: str
262
-
263
- def __post_init__(self):
264
- self.ins_idx = 0
265
-
266
- def _pack_cmd(self) -> list:
267
- return [0x28, 0x10, self.mask << 16 | self.value, self.ins_idx, 0, 0x0000, 0x0000, 0, 0]
268
-
269
-
270
- @dataclass
271
- class QInsEnd(NSQCommand):
272
- def _pack_cmd(self) -> list:
273
- return [0xF8, 0, 0, 0x00000000, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00000000]
274
-
275
-
276
- @dataclass
277
- class QInsCapture(NSQCommand):
278
- width: float
279
- probe_delay: float = 0
280
-
281
- def __post_init__(self):
282
- self.ch_flag = {'all': 3, 'ad': 2, 'da': 1}
283
-
284
- def __bytes__(self):
285
- delay_length = int(round(self.probe_delay/16e-9))
286
- length = int(round(self.width/16e-9))
287
- cmds = [
288
- [0x0002, self.ch_flag['da'], 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, delay_length],
289
- [0x0002, self.ch_flag['all'], 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, length],
290
- ]
291
- return b''.join(self.list2bytes(cmd) for cmd in cmds)
292
-
293
- @staticmethod
294
- def list2bytes(cmd: list):
295
- cmd_raw = struct.pack('=HHHHHHHH', *cmd[::-1])
296
- return cmd_raw
297
-
298
-
299
- @dataclass
300
- class _QInsPTrigDelay(_ProbeCommand):
301
- tag: str = field(kw_only=True)
302
- delay: float
303
-
304
- def __post_init__(self):
305
- self.ch_flag = {'all': 3, 'ad': 2, 'da': 1}
306
-
307
- def _pack_cmd(self) -> list:
308
- length = int(round(self.delay / 16e-9))
309
- return [0x0002, self.ch_flag['all'], 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, length]
310
-
311
-
312
- @dataclass
313
- class _QInsPWaitTrig(_ProbeCommand):
314
- def _pack_cmd(self) -> list:
315
- return [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000]
316
-
317
-
318
- @dataclass
319
- class _QInsPJump(_ProbeCommand):
320
- target: str
321
-
322
- def __post_init__(self):
323
- self.ins_idx = 0
324
-
325
- def _pack_cmd(self) -> list:
326
- return [0x0003, 0x0000, 0x0000, self.ins_idx, 0x0000, 0x0000, 0x0000, 0x0000]
327
-
328
-
329
- class Assembler(GenTagMixin):
330
- def __init__(self, ch_map=None):
331
- if ch_map is None:
332
- ch_map = {
333
- 1: [3, 4, 5, 6, 7, 8],
334
- 2: [11, 12, 13, 14, 15, 16]
335
- }
336
- self.ch_map = ch_map
337
- self.drive2probe = {j: i for i in ch_map.keys() for j in ch_map[i]}
338
- self.raw_cmdq = {j: [] for i in ch_map.values() for j in i}
339
- self.probe_cmdq = {i: [] for i in ch_map.keys()}
340
- self.drive_cmdq = {j: [] for i in ch_map.values() for j in i}
341
-
342
- self.envelop_cache = {
343
- j: np.zeros((global_config['envelope_cache'] // 2,), dtype=np.int16) for i in ch_map.values() for j in i
344
- }
345
-
346
- self.frame_symbol = {j: {} for i in ch_map.values() for j in i}
347
- self.envelop_symbol = {j: {} for i in ch_map.values() for j in i}
348
- self.drive_symbol = {j: {} for i in ch_map.values() for j in i}
349
- self.probe_symbol = {i: {} for i in ch_map.keys()}
350
-
351
- def set_chnl_cmdq(self, ch_id, cmdq):
352
- if ch_id not in self.drive2probe:
353
- raise AssemblyError(f'OUT channel {ch_id} does not exist')
354
- self.raw_cmdq[ch_id] = cmdq
355
- self.envelop_symbol[ch_id], cmdq = self.extract_envelop(ch_id, cmdq)
356
- self.frame_symbol[ch_id] = self.extract_frame(cmdq)
357
- (self.drive_cmdq[ch_id], self.probe_cmdq[self.drive2probe[ch_id]],
358
- self.drive_symbol[ch_id], self.probe_symbol[self.drive2probe[ch_id]]) = self.divide_cmd(ch_id, cmdq)
359
-
360
- def extract_envelop(self, ch_id, cmdq: List[NSQCommand]) -> "Tuple[dict, List[NSQCommand]]":
361
- """!
362
- 在指令队列中提取包络指令,并建立符号表
363
-
364
- @param ch_id:
365
- @param cmdq:
366
- @return:
367
- """
368
- res_cmdq, envelops = [], []
369
- for cmd in cmdq:
370
- if not isinstance(cmd, QInsEnvelop):
371
- res_cmdq.append(copy.copy(cmd))
372
- else:
373
- envelops.append(cmd)
374
-
375
- cache = self.envelop_cache[ch_id]
376
- # 给cache头部打上包络更新指令包头
377
- cache[:16] = global_config['envelope_head']
378
- data_cache = cache[16:]
379
- data_cache[:] = 0
380
-
381
- start = 0
382
- symbol_map = {}
383
- for env in envelops:
384
- wave = bytes(env)
385
- length = len(wave)
386
- end = start + length
387
- data_cache[start//2:end//2] = np.frombuffer(wave, dtype=global_config['envelope_dtype'])
388
- env.envelop_slice = slice(start, end, length)
389
- start += length
390
- symbol_map[env.tag] = env
391
- return symbol_map, res_cmdq
392
-
393
- @staticmethod
394
- def extract_frame(cmdq: List[NSQCommand]) -> "dict":
395
- """!
396
- 在指令队列中提取包络配置指令,并且建立包络符号表
397
-
398
- @param cmdq:
399
- @return:
400
- """
401
- frames = []
402
- for cmd in cmdq:
403
- if not isinstance(cmd, QInsFrame):
404
- continue
405
- frames.append(cmd)
406
-
407
- symbol_map = {}
408
- for idx, frame in enumerate(frames):
409
- frame.frame_idx = idx
410
- symbol_map[frame.tag] = frame
411
- return symbol_map
412
-
413
- def divide_cmd(self, ch_id, cmdq) -> "Tuple[list, list, dict, dict]":
414
- """!
415
-
416
- @param ch_id:
417
- @param cmdq:
418
- @return:
419
- """
420
- drive_queue, probe_queue, drive_symbol, probe_symbol = self._link_wave(ch_id, cmdq)
421
- drive_queue, drive_symbol = self._optimize_drive_q(drive_queue, drive_symbol)
422
- probe_queue, probe_symbol = self._optimize_probe_q(probe_queue)
423
- drive_queue, probe_queue = self._link_jump(drive_queue, probe_queue, drive_symbol, probe_symbol)
424
- return drive_queue, probe_queue, drive_symbol, probe_symbol
425
-
426
- def _link_wave(self, ch_id, cmdq):
427
- """!
428
- 建立frame和envelop到指令的关联,并生成基础的指令符号表,初步分割drive与probe的指令
429
-
430
- @param ch_id:
431
- @param cmdq:
432
- @return:
433
- """
434
- symbols = ChainMap(self.frame_symbol[ch_id], self.envelop_symbol[ch_id])
435
- drive_queue, probe_queue, drive_symbol, probe_symbol = [], [], {}, {}
436
- probe_queue.append(_QInsPWaitTrig(tag=self.generate_tag))
437
- probe_symbol[probe_queue[-1].tag] = 0
438
-
439
- for cmd in cmdq:
440
- if hasattr(cmd, 'frame_idx') and hasattr(cmd, 'frame'):
441
- frame: QInsFrame = symbols.get(cmd.frame, None)
442
- if frame is None:
443
- raise AssemblyError(f'The frame tag required by instruction {cmd} '
444
- f'does not exist in the instruction queue of channel {ch_id}')
445
- cmd.frame_idx = frame.frame_idx
446
- if hasattr(cmd, 'envelop_slice') and hasattr(cmd, 'envelop'):
447
- envelop: QInsEnvelop = symbols.get(cmd.envelop, None)
448
- if envelop is None:
449
- raise AssemblyError(f'The envelop tag required by instruction {cmd} '
450
- f'does not exist in the instruction queue of channel {ch_id}')
451
- cmd.envelop_slice = envelop.envelop_slice
452
- if isinstance(cmd, QInsCapture):
453
- # 这里要保证占capture位置的playzero指令依然能被跳转
454
- wait = QInsPlayZero(tag=cmd.tag, width=cmd.width + cmd.probe_delay)
455
- cmd.tag = self.generate_tag
456
- drive_queue.append(wait)
457
- probe_queue.append(cmd)
458
- else:
459
- wait = _QInsPTrigDelay(tag=self.generate_tag, delay=cmd.overhead)
460
- drive_queue.append(cmd)
461
- probe_queue.append(wait)
462
- drive_symbol[drive_queue[-1].tag] = len(drive_queue)-1
463
- probe_symbol[probe_queue[-1].tag] = len(probe_queue)-1
464
- probe_queue.append(_QInsPJump(target=probe_queue[0].tag, tag=self.generate_tag))
465
- probe_symbol[probe_queue[-1].tag] = len(probe_queue)-1
466
- return drive_queue, probe_queue, drive_symbol, probe_symbol
467
-
468
- def _link_jump(self, drive_queue: List[NSQCommand], probe_queue, drive_symbol, probe_symbol):
469
- """!
470
- 连接指令队列中的跳转指令
471
-
472
- @param drive_queue:
473
- @param probe_queue:
474
- @return:
475
- """
476
- for cmd in drive_queue:
477
- if hasattr(cmd, 'ins_idx') and hasattr(cmd, 'target'):
478
- cmd.ins_idx = drive_symbol[cmd.target]
479
-
480
- for cmd in probe_queue:
481
- if hasattr(cmd, 'ins_idx') and hasattr(cmd, 'target'):
482
- cmd.ins_idx = probe_symbol[cmd.target]
483
- return drive_queue, probe_queue
484
-
485
- def _optimize_probe_q(self, queue):
486
- """!
487
- 优化probe指令队列
488
-
489
- @param queue:
490
- @param symbol:
491
- @return:
492
- """
493
- symbol, idx = {}, 0
494
- cache = []
495
- res_q = []
496
- # 合并所有相邻的_QInsProbeDelay,减少指令队列长度
497
- for cmd in queue:
498
- if isinstance(cmd, _QInsPTrigDelay):
499
- cache.append(cmd)
500
- else:
501
- delay = _QInsPTrigDelay(tag=self.generate_tag, delay=sum(i.delay for i in cache))
502
- if delay.delay != 0:
503
- res_q.append(delay)
504
- symbol[delay.tag] = idx
505
- idx += 1
506
- res_q.append(cmd)
507
- symbol[cmd.tag] = idx
508
- idx += 1
509
- cache = []
510
- return res_q, symbol
511
-
512
- def _optimize_drive_q(self, queue, symbol):
513
- """!
514
- 优化drive指令队列
515
-
516
- @param queue:
517
- @param symbol:
518
- @return:
519
- """
520
- return queue, symbol
521
-
522
- def assemble(self) -> "Tuple[dict, dict, dict]":
523
- envelop_cache = {}
524
- drive_cache = {}
525
- for pch, dch_list in self.ch_map.items():
526
- memory = np.zeros((10240 * 8 * len(dch_list), ), dtype=np.uint32).reshape((len(dch_list), 8*10240))
527
- for idx, ch in enumerate(dch_list):
528
- _data = np.frombuffer(b''.join(bytes(i) for i in self.drive_cmdq[ch]), dtype=np.int32)
529
- memory[idx, :_data.size] = _data
530
- drive_cache[pch] = memory
531
- envelop_cache[pch] = np.array([self.envelop_cache[ch] for ch in dch_list], dtype=np.int16)
532
-
533
- probe_cache = {}
534
- for pch, queue in self.probe_cmdq.items():
535
- memory = np.frombuffer(b''.join(bytes(i) for i in queue), dtype=np.int32)
536
- probe_cache[pch] = memory
537
-
538
- return envelop_cache, drive_cache, probe_cache
@@ -1,14 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: nsqdriver
3
- Version: 0.3.0
4
- Summary: Naishu Q series quantum measurement and control equipment driver interface
5
- Home-page: https://g2hoyqcmh4.feishu.cn/wiki/wikcnzvyMd82DLZUe2NsI6HxsFc
6
- Author: Naishu Technology
7
- Author-email: jilianyi@naishu.tech
8
- Classifier: Intended Audience :: Developers
9
- Classifier: Programming Language :: Python :: 3.10
10
- Classifier: Programming Language :: Python :: 3.11
11
- Requires-Python: >=3.10
12
- Requires-Dist: numpy (>=1.18)
13
- Requires-Dist: waveforms
14
-