Skip to content
Snippets Groups Projects
Commit 8378b9ce authored by Stephan Philips's avatar Stephan Philips
Browse files

updates

parent 4623f30c
No related branches found
No related tags found
No related merge requests found
Showing
with 263 additions and 1 deletion
File added
File added
......@@ -6,10 +6,10 @@ pulse_lib.egg-info/PKG-INFO
pulse_lib.egg-info/SOURCES.txt
pulse_lib.egg-info/dependency_links.txt
pulse_lib.egg-info/top_level.txt
pulse_lib/segments/segments_c_func.c
pulse_lib/segments/__init__.py
pulse_lib/segments/data_classes.py
pulse_lib/segments/data_handling_functions.py
pulse_lib/segments/looping.py
pulse_lib/segments/segments.py
pulse_lib/segments/segments_IQ.py
pulse_lib/segments/segments_base.py
......
import numpy as np
class Memory_manager():
"""
Object that manages the occupation of the memory of the AWG.
The Memory is pre-segmented on the AWG. E.g you have to say that you want to be able to upload 100 sequences with lenth L.
Currently this is a simple system that just assigns memory locations to certain segments.
There is are currently no advanced capabilities build in to reuse the memory in the AWG. This could be done later if performance would be limiting.
A compelling reason not to reuse segments would be in the assumption one would regularly use DSP which would make it hard to reuse things.
"""
def __init__(self, AWG, RAM_QTY):
'''
Initialize memory management object.
'''
# make division of memory[ HARDCODED ...]: (assume sorted from big to small)
memory_cells = [
[1e8,4],
[5e7,4],
[1e7,4],
[5e6,8],
[1e6,40],
[1e5,500],
[1e4,5000],
[5e3,20000],
[1e3,50000]
]
# m = 0
# for i in memory_cells:
# m += i[0]*i[1]
# print(m, 'n_points')
self.segm_occup = segment_occupation_AWG(memory_cells)
def get_upload_slot(self, n_points):
'''
get a location where the data can be uploaded in the memory.
Args:
n_points (int) : number of points that will be saved in the memory
returns:
segment_number (int) : the segment number where the segment can be uploaded to in the memory of the AWG.
'''
seg_number, max_size = self.segm_occup.request_new_segment(n_points)
return seg_number
def release_memory(self,segments):
'''
release memory when segments are not longer needed.
Args:
segments (array<int>) : list with segments number to be released
'''
for i in segments:
self.segm_occup.free_segment(i)
class segment_occupation_AWG():
"""
Object that manages the occupation of the memory of the AWG.
The Memory is pre-segmented on the AWG. E.g you have to say that you want to be able to upload 100 sequences with lenth L.
Currently this is a simple system that just assigns memory locations to certain segments.
There is are currently no advanced capabilities build in to reuse the memory in the AWG. This could be done later if performance would be limiting.
A compelling reason not to reuse segments would be in the assumption one would regularly use DSP which would make it hard to reuse things.
"""
def __init__(self, segment_distribution):
self.segment_distribution = np.array(segment_distribution)
self.memory_sizes = np.sort(self.segment_distribution[:,0])
self.index_info = np.zeros([len(self.memory_sizes)])
seg_data = []
k = 0
for i in segment_distribution:
seg_numbers = np.arange(i[1]) + k
self.index_info[len(seg_data)] = k
k += i[1]
seg_data.append((i[0], seg_numbers))
self.seg_data = dict(seg_data)
def request_new_segment(self,size):
'''
Request a new segment in the memory with a certain size
Args:
size (int) : size you want to reserve in the AWG memory
'''
valid_sizes = np.where(size < self.memory_sizes)[0]
for i in valid_sizes:
seg_numbers = self.seg_data[self.memory_sizes[i]]
if len(seg_numbers) > 0 :
my_segnumber = seg_numbers[0]
self.seg_data[self.memory_sizes[i]] = seg_numbers[1:]
return my_segnumber, self.memory_sizes[i]
# means no segment available
return -1, 0
def free_segment(self, seg_number):
'''
adds a segment as free back to the usable segment pool
Args:
seg_number (int), number of the segment in the ram of the AWG
'''
seg_loc = np.max(np.where(seg_number >= self.index_info)[0])+1
seg_numbers = self.seg_data[self.memory_sizes[-seg_loc]]
seg_numbers = np.append(seg_numbers, seg_number)
self.seg_data[self.memory_sizes[-seg_loc]] = seg_numbers
\ No newline at end of file
File added
File added
from distutils.core import setup
from Cython.Build import cythonize
import os
import numpy
# for some reason I have to include manually to make it work ..
os.environ['CFLAGS'] = '-I' + numpy.get_include()
setup(
name = 'test`',
ext_modules= cythonize("test.pyx", include_path = [numpy.get_include()]),
)
#error Do not use this file, it is the result of a failed Cython compilation.
File added
File added
File added
import cython
import numpy as np
cimport numpy as np
@cython.final
cdef class test_class:
cdef int number_of_bla
def __cinit__(self, number):
self.number_of_bla = number
def get_number(self):
return self.number_of_bla
cdef int get_number_fast(self) nogil:
return self.number_of_bla
cdef class data_container(np.ndarray):
def __cinit__(subtype, input_type=None, shape = (1,)):
obj = super(data_container, subtype).__new__(subtype, shape, object)
if input_type is not None:
obj[0] = input_type
# return obj
cdef test_class my_test = test_class(1)
cdef int undef
np_arr = np.empty([1,5], dtype=test_class)
cdef test_class [:,:] arr = np_arr
np_arr[0,1] = test_class(2)
print(arr.base)
with nogil:
undef = my_test.get_number_fast()
undef = arr[0,1].get_number_fast()
print(undef)
\ No newline at end of file
import threading as th
import numpy as np
from pulse_lib.Keysight.AWG_memory_manager import Memory_manager
def mk_thread(function):
def wrapper(*args, **kwargs):
thread = th.Thread(target=function, args=args, kwargs=kwargs)
thread.start()
return thread
return wrapper
class keysight_uploader():
"""
Object responsible for uploading waveforms to the keysight AWG in a timely fashion.
"""
def __init__(self, AWGs, channel_locations, channel_delays):
'''
Initialize the keysight uploader.
Args:
AWGs (list<QcodesIntrument>) : list with AWG's
channel_locations (dict): dict with channel and AWG+channel location
Returns:
None
'''
self.memory_allocation = dict()
# TODO reinit memory on start-up
for i in AWG:
self.memory_allocation[i.name]= Memory_manager()
self.channel_map = channel_locations
self.channel_delays = channel_delays
self.upload_queue = []
self.upload_done = []
def add_upload_job(self, job):
'''
add a job to the uploader.
Args:
job (upload_job) : upload_job object that defines what needs to be uploaded and possible post processing of the waveforms (if needed)
'''
self.upload_queue.append(job)
def get_segment_data(self, job):
'''
get the segment numbers where an upload has been performed.
Args:
job (type?) :
Returns:
dict <array <int> >: map with with the channels where the segments have been uploaded
'''
pass
def __get_new_job(self):
'''
get the next job that needs to be uploaded.
'''
# @mk_thread
def uploader(self):
'''
Class taking care of putting the waveform on the right AWG. This is a continuous thread that is run in the background.
Steps:
1) get all the upload data
2) perform DC correction (if needed)
3) perform DSP correction (if needed)
4) upload all data
5) write in the job object the resulting locations of sequences that have been uploaded.
'''
job = self.get_new_job(self)
upload_data = dict()
class upload_job(object):
"""docstring for upload_job"""
def __init__(self, sequence, index=0, neutralize=True, priority=0):
self.sequence = sequence
self.index = index
self.neutralize = True
self.priority = priority
self.DSP = False
def add_dsp_function(self, DSP):
self.DSP =True
self.DSP_func = DSP
def assign_upload_locations(self):
pass
File added
No preview for this file type
File added
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment