[docs]classMemoryManager:""" Memory manager for AWG memory. AWG memory is reserved in slots of sizes from 1e4 till 1e8 samples. Allocation of memory takes time. So, only request a high maximum waveform size when it is needed. Memory slots (number: size): 400: 1e4 samples 100: 1e5 samples 20: 1e6 samples 8: 1e7 samples 4: 1e8 samples Args: waveform_size_limit: maximum waveform size to support. """verbose=False
@dataclassclass_MemorySlot:number:intsize:intallocated:boolinitialized:boolallocation_ref:int'''Unique reference value when allocated. Used to check for incorrect or missing release calls. '''allocation_time:str=''# Note (M3202A): size must be multiples of 10 and >= 2000memory_sizes=[(int(1e4),400),(int(1e5),100),(int(1e6),20),(int(1e7),8),# Uploading 8e7 samples takes 1.5s.(int(1e8),4)# Uploading 4e8 samples takes 7.3s.]def__init__(self,log,waveform_size_limit:int=int(1e6))->None:self._log=logself._allocation_ref_count:int=0self._created_size:int=0self._max_waveform_size:int=0self._free_memory_slots:Dict[int,List[int]]={}self._slots:List[MemoryManager._MemorySlot]=[]self._slot_sizes=sorted([sizeforsize,_inMemoryManager.memory_sizes])self.set_waveform_limit(waveform_size_limit)
[docs]defset_waveform_limit(self,waveform_size_limit:int)->None:""" Increases the maximum size of waveforms that can be uploaded. Additional memory will be reserved in the AWG. Limit can not be reduced, because reservation cannot be undone. Args: waveform_size_limit: maximum size of waveform that can be uploaded """ifwaveform_size_limit>max(self._slot_sizes):raiseException(f'Requested waveform size {waveform_size_limit} 'f'is too big')self._max_waveform_size=waveform_size_limitself._create_memory_slots(waveform_size_limit)
[docs]defget_uninitialized_slots(self)->List['MemoryManager._MemorySlot']:""" Returns list of slots that must be initialized (reserved in AWG) """new_slots=[]slots=self._slots.copy()forslotinslots:ifnotslot.initialized:new_slots.append(slot)slot.initialized=Truereturnnew_slots
[docs]defallocate(self,wave_size:int)->'MemoryManager.AllocatedSlot':""" Allocates a memory slot with at least the specified wave size. Args: wave_size: number of samples of the waveform Returns: allocated slot """ifwave_size>self._max_waveform_size:raiseException(f'AWG wave with {wave_size} samples is too long. 'f'Max size={self._max_waveform_size}. Increase 'f'waveform size limit with set_waveform_limit().')forslot_sizeinself._slot_sizes:ifwave_size>slot_size:continueifslot_size>self._created_size:# slots of this size are not initialized.breakiflen(self._free_memory_slots[slot_size])>0:slot=self._free_memory_slots[slot_size].pop(0)self._allocation_ref_count+=1self._slots[slot].allocation_ref=self._allocation_ref_countself._slots[slot].allocated=Trueself._slots[slot].allocation_time=datetime.now().strftime('%H:%M:%S.%f')ifMemoryManager.verbose:self._log.debug(f'Allocated slot {slot}')returnMemoryManager.AllocatedSlot(slot,self._slots[slot].allocation_ref,self)raiseException(f'No free memory slots left for waveform with'f' {wave_size} samples.')
[docs]defrelease(self,allocated_slot:AllocatedSlot)->None:""" Releases the `allocated_slot`. """slot_number=allocated_slot.numberslot=self._slots[slot_number]ifnotslot.allocated:raiseException(f'memory slot {slot_number} not in use')ifslot.allocation_ref!=allocated_slot.allocation_ref:raiseException(f'memory slot {slot_number} allocation reference 'f'mismatch:{slot.allocation_ref} is not equal to 'f'{allocated_slot.allocation_ref}')slot.allocated=Falseslot.allocation_ref=0self._free_memory_slots[slot.size].append(slot_number)ifMemoryManager.verbose:try:self._log.debug(f'Released slot {slot_number}')except:# self._log throws exception when instrument has been closed.logging.debug(f'Released slot {slot_number}')
[docs]defrelease_all(self)->None:""" Release all allocated slots regardless of external references. """forslotinself._slots:ifslot.allocated:self._log.info(f'Forced release of slot {slot.number} 'f'allocated at {slot.allocation_time}')slot.allocated=Falseslot.allocation_ref=0self._free_memory_slots[slot.size].append(slot.number)
def_create_memory_slots(self,max_size:int)->None:creation_limit=self._get_slot_size(max_size)free_slots=self._free_memory_slotsslots=self._slotsforsize,amountinsorted(MemoryManager.memory_sizes):ifsize>creation_limit:breakifsize<=self._created_size:continuefree_slots[size]=[]foriinrange(amount):number=len(slots)free_slots[size].append(number)slots.append(MemoryManager._MemorySlot(number,size,False,False,0))self._free_memory_slots=free_slotsself._slots=slotsself._created_size=creation_limitdef_get_slot_size(self,size:int)->int:forslot_sizeinself._slot_sizes:ifslot_size>=size:returnslot_sizeraiseException(f'Requested waveform size {size} is too big')