class Coincidence_Timer: def __init__(self, mode): if mode == 0: self.PC_OV = Overlay("TDC/TDC_OVERLAY_wrapper.bit", 0) print("Loaded two channel coincidence rising edge TDC") elif mode == 1: self.PC_OV = Overlay("TDC/SC_TDC_OVERLAY.bit", 0) print("Loaded single channel inter rising edge TDC") else: print("What?") self.PC_OV = Overlay("TDC/TDC_OVERLAY_wrapper.bit", 0) print("Loaded two channel coincidence rising edge TDC") self.PC_OV.download() self.GPIO = MMIO(it_a_gpio_addr, axi_gpio_range) self.GPIO_INT = MMIO(it_a_gpioi_addr, axi_gpio_range) self.GPIO.write(ch1_dir, 0xFFFFFFFF) self.GPIO.write(ch2_dir, 0x0) self.GPIO_INT.write(ch1_dir, 0xFFFFFFFF) self.GPIO.write(ch2_data, 0x0) #Hold system in reset for now def arm_and_wait(self): self.GPIO.write(ch2_data, 0x1) op = 0 while (self.GPIO_INT.read(ch1_data) == 0x0): pass if (self.GPIO_INT.read(ch1_data) == 0x1): op = self.GPIO.read(ch1_data) self.GPIO.write(ch2_data, 0x0) return op def tval_to_time(self, tval): return tval * (1 / 450000000)
def __init__(self, chunkSize, numClasses, numFeatures): self.numClasses = numClasses self.numFeatures = numFeatures # ------------------------- # Download Overlay. # ------------------------- ol = Overlay("LogisticRegression.bit") ol.download() # ------------------------- # Physical address of the Accelerator Adapter IP. # ------------------------- ADDR_Accelerator_Adapter_BASE = int(PL.ip_dict["SEG_LR_gradients_kernel_accel_0_if_Reg"][0], 16) ADDR_Accelerator_Adapter_RANGE = int(PL.ip_dict["SEG_LR_gradients_kernel_accel_0_if_Reg"][1], 16) # ------------------------- # Initialize new MMIO object. # ------------------------- self.bus = MMIO(ADDR_Accelerator_Adapter_BASE, ADDR_Accelerator_Adapter_RANGE) # ------------------------- # Physical addresses of the DMA IPs. # ------------------------- ADDR_DMA0_BASE = int(PL.ip_dict["SEG_dm_0_Reg"][0], 16) ADDR_DMA1_BASE = int(PL.ip_dict["SEG_dm_1_Reg"][0], 16) ADDR_DMA2_BASE = int(PL.ip_dict["SEG_dm_2_Reg"][0], 16) ADDR_DMA3_BASE = int(PL.ip_dict["SEG_dm_3_Reg"][0], 16) # ------------------------- # Initialize new DMA objects. # ------------------------- self.dma0 = DMA(ADDR_DMA0_BASE, direction = DMA_TO_DEV) # data1 DMA. self.dma1 = DMA(ADDR_DMA1_BASE, direction = DMA_TO_DEV) # data2 DMA. self.dma2 = DMA(ADDR_DMA2_BASE, direction = DMA_TO_DEV) # weights DMA. self.dma3 = DMA(ADDR_DMA3_BASE, direction = DMA_FROM_DEV) # gradients DMA. # ------------------------- # Allocate physically contiguous memory buffers. # ------------------------- self.dma0.create_buf(int(chunkSize / 2) * (self.numClasses + (1 + self.numFeatures)) * 4, 1) self.dma1.create_buf(int(chunkSize / 2) * (self.numClasses + (1 + self.numFeatures)) * 4, 1) self.dma2.create_buf((self.numClasses * (1 + self.numFeatures)) * 4, 1) self.dma3.create_buf((self.numClasses * (1 + self.numFeatures)) * 4, 1) # ------------------------- # Get CFFI pointers to objects' internal buffers. # ------------------------- self.data1_buf = self.dma0.get_buf(32, data_type = "float") self.data2_buf = self.dma1.get_buf(32, data_type = "float") self.weights_buf = self.dma2.get_buf(32, data_type = "float") self.gradients_buf = self.dma3.get_buf(32, data_type = "float")
def __init__(self): ol = Overlay("DDR_CT_TEST_OV_wrapper.bit", 0) ol.download() self.DATA = MMIO(0x41200000, 0x10000) self.UTIL = MMIO(0x41210000, 0x10000) self.DEBUG = MMIO(0x41220000, 0x10000) self.UTIL.write(0x0, 0x0) self.UTIL.write(0x8, 0b0)
def __init__(self): ol = Overlay("TEST_wrapper.bit",0) ol.download() self.DELAY = MMIO(0x41200000,0x10000) self.CTIME0 = MMIO(0x41210000,0x10000) self.CTIME1 = MMIO(0x41220000,0x10000) self.O_UTIL = MMIO(0x41230000,0x10000) self.I_UTIL = MMIO(0x41240000,0x10000)
class pz1sofi(): """Class to control the Sobel filter hardware Attributes ---------- bitfile : str Absolute path to bitstream libfile : str Absolute path to shared library overlay : Overlay Pynq-Z1 Sobel filter overlay frame_gray : Pointer to intermediate gray image """ def __init__(self): #Set attributes self.bitfile = BITFILE self.libfile = LIBFILE self._ffi = cffi.FFI() #Accelerator functions self._ffi.cdef("void _p0_rgb_2_gray_0(uint8_t * input," + "uint8_t * output);") self._ffi.cdef("void _p0_sobel_filter_0(uint8_t * input," + "uint8_t * output);") self._ffilib = self._ffi.dlopen(LIBFILE) self.overlay = Overlay(self.bitfile) #XLNK functions self._ffi.cdef("void *cma_alloc(uint32_t len," + "uint32_t cacheable);") self._ffi.cdef("void cma_free(void *buf);") #Allocate memory for gray frame self.frame_gray = self._ffi.cast( "uint8_t *", self._ffilib.cma_alloc(1920 * 1080, 0)) #Check if bitstream is loaded if not Overlay.is_loaded(self.overlay): self.overlay.download() def get_frame_ptr(self, hdmi_in_frame): """... """ return self._ffi.cast("uint8_t *", hdmi_in_frame.frame_addr()) def sobel_filter(self, frame_in, frame_out, num_frames=1, get_fps=False): """... """ if get_fps: import time time1 = time.time() for i in range(num_frames): self._ffilib._p0_rgb_2_gray_0(frame_in, self.frame_gray) self._ffilib._p0_sobel_filter_0(self.frame_gray, frame_out) if get_fps: time2 = time.time() return num_frames / (time2 - time1) def __del__(self): #Deallocate memory for gray frame self._ffilib.cma_free(self._ffi.cast("void *", self.frame_gray))
class ST: def __init__(self): self.ov = Overlay("TEST_wrapper.bit", 0) self.ov.download() self.DATA = MMIO(0x41200000, 0x10000) self.UTIL = MMIO(0x41210000, 0x10000) self.DELAY0 = MMIO(0x41220000, 0x10000) self.DELAY1 = MMIO(0x41230000, 0x10000) self.DEBUG = MMIO(0x41240000, 0x10000) self.DUTIL = MMIO(0x41250000, 0x10000) log.info("Ready") def wait_for_rdy(self): while (self.UTIL.read(0x8) == 0): pass def read_time(self): course_time = self.DATA.read(0x0) log.debug("CT: " + str(course_time)) finetimes = self.DATA.read(0x8) preftime = finetimes & 0xFF postftime = (finetimes & 0xFF00) >> 8 log.debug("PRE: " + str(preftime)) log.debug("POST: " + str(postftime)) timetoconv = preftime - postftime timetoconv *= FTIME time = course_time / COURSE_CLK + timetoconv return time def proc(self): self.DUTIL.write(0x0, 0x1) sleep(0.1) self.UTIL.write(0x0, 0x1) self.wait_for_rdy() self.read_debug() time = self.read_time() log.info("TIME: " + str(time * 1e9)) self.UTIL.write(0x0, 0x0) self.DUTIL.write(0x0, 0x0) return time def set_delays(self, dels): #self.DUTIL.write(0x0,0x1) self.DELAY0.write(0x0, int(dels[0])) self.DELAY0.write(0x8, int(dels[1])) self.DELAY1.write(0x0, int(dels[2])) self.DELAY1.write(0x8, int(dels[3])) #self.DUTIL.write(0x0,0x1) def read_debug(self): staten = self.DEBUG.read(0x0) for i in range(8): mask = 0xF log.debug("STATEN" + str(i) + ": " + format((staten >> (4 * i)) & mask, '#006b')) log.debug("STATENFULL: " + bin(staten)) log.debug("STATEL: " + bin(self.DEBUG.read(0x8)))
def __init__(self): ol = Overlay("TEST_wrapper.bit", 0) ol.download() self.DATA = MMIO(0x43c00000, 0x10000) self.UTIL = MMIO(0x43c10000, 0x10000) self.loaded_data = [] for i in range(FIFO_BUFFER): self.loaded_data.append(0) self.loaded_count = 0
def __init__(self): ol = Overlay("SCS_TT_TEST_wrapper.bit", 0) ol.download() self.UTIL = MMIO(0x41200000, 0x10000) self.UTIL.write(0x8, int(REF_CLK)) self.DATA0 = MMIO(0x41210000, 0x10000) self.DATA1 = MMIO(0x41220000, 0x10000) self.DATA_UTIL = MMIO(0x41230000, 0x10000) self.DEBUG0 = MMIO(0x41240000, 0x10000) self.DEBUG1 = MMIO(0x41250000, 0x10000)
class clock_gen: def __init__(self): self.PC_OV = Overlay("TDC/PG_OV_wrapper.bit", 0) self.PC_OV.download() self.CLK_WIZ = MMIO(BASE_ADDR, 0x10000) self.CLK_WIZ.write(CCON0, 0xA01) self.CLK_WIZ.write(CCON2, 0x5) while (self.CLK_WIZ.read(SR) == 0): pass self.CLK_WIZ.write(CCON23, 0x3)
def __init__(self): ol = Overlay("TEST_wrapper.bit",0) ol.download() self.CONFIG = MMIO(0x43c00000,0x10000) self.DATA0 = MMIO(0x43c10000,0x10000) self.DATA1 = MMIO(0x43c20000,0x10000) self.DELAY = MMIO(0x43c30000,0x10000) self.UTIL = MMIO(0x43c40000,0x10000) self.loaded_data = [] for i in range(FIFO_DEPTH): self.loaded_data.append(0) self.loaded_count = 0
def init_accelerator(self, bit_file=TINIER_YOLO_BIT_FILE, json_network=W1A3_JSON, json_layer=JSON_TINIER_YOLO): """ Initialize accelerator memory and configuration. """ if bit_file : ol = Overlay(bit_file) ol.download() if not self.init: with open(json_network, 'r') as f: self.network_json = json.load(f) with open(json_layer, 'r') as f: self.layer_json = json.load(f) self.lib.initParameters(1,0); self.lib.initAccelerator(json_network.encode(), json_layer.encode()) self.init = True
class PulseCounter: def __init__(self): self.PC_OV = Overlay("TDC/Counter_Overlay_wrapper.bit", 0) self.PC_OV.download() self.GPIO_DATA = [] self.GPIO_UTILITY = [] for i in range(4): self.GPIO_DATA.append( MMIO(axi_gpio_base_addr + 2 * i * axi_gpio_range, axi_gpio_range)) self.GPIO_DATA[i].write(ch1_dir, 0xFFFFFFFF) self.GPIO_DATA[i].write(ch2_dir, 0x0) self.GPIO_DATA[i].write(ch2_data, 0xFFFFFFFF) for i in range(4): self.GPIO_UTILITY.append( MMIO(axi_gpio_base_addr + (1 + 2 * i) * axi_gpio_range, axi_gpio_range)) self.GPIO_UTILITY[i].write(ch1_dir, 0x0) self.GPIO_UTILITY[i].write(ch1_data, 0x0) self.GPIO_UTILITY[i].write(ch2_dir, 0xFFFFFFFF) # Sets the timer threshold (window of counting) for all channels (cannot set different windows for individual channels def set_threshold(self, val): newval = int(val) for i in range(4): self.GPIO_DATA[i].write(ch2_data, newval) # Reads the counts of each channel and returns a 4 size vector containing counts for each channel def read_incidents(self): return [self.GPIO_DATA[i].read(ch1_data) for i in range(4)] # Reads the status of the counting, if its finished or not, as there are 4 channels, the result is a 4 bit integer def read_utility(self): outpi = 0x0 for i in range(4): outpi = outpi | (self.GPIO_UTILITY[i].read(ch2_data) & 0B1) << i #return self.GPIO_UTILITY[0].read(ch2_data) #print(bin(outpi)) return outpi # Allows setting of the reset lines to the pulse counter and timer of all channels (cannot individually reset channels) def set_ctl_lines(self, r0, r1, EN): val = r1 << 1 | r0 val = val | EN << 1 for i in range(4): self.GPIO_UTILITY[i].write(ch1_data, val)
def init_accelerator(self, bit_file=DOREFANET_BIT_FILE, json_network=W1A2_JSON, json_layer=DOREFANET_LAYER_JSON): """ Initialize accelerator memory and configuration. """ if bit_file : ol = Overlay(bit_file) ol.download() if not self.init: with open(json_network, 'r') as f: self.network_json = json.load(f) with open(json_layer, 'r') as f: self.layer_json = json.load(f) self.lib.initParameters(1,0); self.lib.initAccelerator(json_network.encode(), json_layer.encode()) self.init = True
def download_bitstream(self): """Download the bitstream Downloads the bitstream onto hardware using overlay class. Also gives you access to overlay. Parameters ---------- None Returns ------- None """ global ws2812_overlay ws2812_overlay = Overlay(self.bitfile) ws2812_overlay.download()
def __init__(self): self.ffi = cffi.FFI() if IS_PYNQ: bitfile = "../pynq_chainer/HLS/bitstream.bit" libfile = "../pynq_chainer/HLS/src/libaccel.so" #self.ffi.cdef("int _Z18_p0_mmult_accel1_0PfS_S_iii(float*, float*, float*, int, int, int);") self.ffi.cdef( "int _Z17_p0_mmult_accel_0PfS_S_iii(float*, float*, float*, int, int, int);" ) self.lib = self.ffi.dlopen(libfile) #self.accel_fn = self.lib._Z18_p0_mmult_accel1_0PfS_S_iii self.accel_fn = self.lib._Z17_p0_mmult_accel_0PfS_S_iii overlay = Overlay(bitfile) if not overlay.is_loaded(): overlay.download() print("load Overlay") else: self.accel_fn = pcsim.mmult_accel
class HuffmanEncodingCore(Singleton): def __init__(self): self.overlay = Overlay('huffman_core_wrapper/bitstream/irq-test.bit') self.overlay.download() self.huff_core = self.overlay.huffman_encoding_0 def start_calc(self): # enable interrupt self.huff_core.write(ip_intr_en_addr, 1) # read done interrupt self.huff_core.write(ip_intr_status_addr, 1) # start self.huff_core.write(ctrl_base_addr, 1) def feed_data(self, freq_table): if (not freq_table): return # write symbol and frequency to huffman core for idx, ele in enumerate(freq_table): # write to encoding core memory if (not ele == None): (val, freq) = ele self.huff_core.write(sym_histo_val_addr + 4 * idx, ord(val)) self.huff_core.write(sym_histo_freq_addr + 4 * idx, freq) def read_code_word(self, freq_table): encoding = {'symbol': [], 'total': 0} for idx, ele in enumerate(freq_table): if (not ele == None): (val, freq) = ele encoding['symbol'].append( self.huff_core.read(encoding_addr + 4 * ord(val))) encoding['total'] = self.huff_core.read(non_zero_cnt_data_addr) return encoding def calc_encoding(self, freq_table): self.feed_data(freq_table) start = time.time() self.start_calc() end = time.time() encoding = self.read_code_word(freq_table) return {'encoding': encoding, 'consume': end - start}
class mcolorl: def __init__(self): self.mcolv = Overlay("mcolor/design_1_wrapper.bit", 0) self.mcolv.download() self.axi_gpio_h = MMIO(axi_gpio_addr, axi_gpio_range) self.axi_gpio_h.write(0x4, 0x0) self.axi_gpio_h.write(0x0, 0x0) self.buffer = 0 def led(self, led, r, g, b): shift = 0 if (led == 1): shift = 3 self.buffer = self.buffer | (int(str(r) + str(g) + str(b), 2) << shift) self.axi_gpio_h.write(0x0, self.buffer) def cust(self, val): self.axi_gpio_h.write(0x0, val) def clrbuf(self): self.buffer = 0 self.axi_gpio_h.write(0x0, self.buffer)
def test_mmio(): """Test whether MMIO class is working properly. Generate random tests to swipe through the entire range: >>> mmio.write(all offsets, random data) Steps: 1. Initialize an instance with length in bytes 2. Write an integer to a given offset. 3. Write a number within the range [0, 2^32-1] into a 4-byte location. 4. Change to the next offset and repeat. """ ol = Overlay('base.bit') ol.download() sleep(0.2) mmio_base = ol.ip_dict['SEG_mb_bram_ctrl_1_Mem0'][0] mmio_range = ol.ip_dict['SEG_mb_bram_ctrl_1_Mem0'][1] mmio = MMIO(mmio_base, mmio_range) for offset in range(0, 100, general_const.MMIO_WORD_LENGTH): data1 = randint(0, pow(2,32)-1) mmio.write(offset, data1) sleep(0.02) data2 = mmio.read(offset) assert data1==data2, \ 'MMIO read back a wrong random value at offset {}.'.format(offset) mmio.write(offset, 0) sleep(0.02) assert mmio.read(offset)==0, \ 'MMIO read back a wrong fixed value at offset {}.'.format(offset) del ol
def __init__(self): self.ffi = cffi.FFI() if IS_PYNQ: bitfile = "../pynq_chainer/HLS/bitstream.bit" libfile = "../pynq_chainer/HLS/src/libaccel.so" #self.ffi.cdef("void _Z17_p0_mmult_accel_0PiS_S_ii(int*, int*, int*, int, int);") #self.ffi.cdef("void _Z20_p0_binary_connect_0tPiS_S_tt(unsigned short, int*, int*, int*, unsigned short, unsigned short);") self.ffi.cdef( "void _Z17_p0_BlackBoxJam_0P7ap_uintILi32EES1_bjjjS0_(unsigned int*, unsigned int*, bool, unsigned int, unsigned int, unsigned int, unsigned int);" ) self.lib = self.ffi.dlopen(libfile) print(self.lib.__dict__) #self.accel_fn = self.lib._Z17_p0_mmult_accel_0PiS_S_ii #self.accel_fn = self.lib._Z20_p0_binary_connect_0tPiS_S_tt self.accel_fn = self.lib._Z17_p0_BlackBoxJam_0P7ap_uintILi32EES1_bjjjS0_ overlay = Overlay(bitfile) if not overlay.is_loaded(): overlay.download() print("load Overlay") else: self.accel_fn = pcsim.mmult_accel
def test_mmio(): """Test whether MMIO class is working properly. Generate random tests to swipe through the entire range: >>> mmio.write(all offsets, random data) Steps: 1. Initialize an instance with length in bytes 2. Write an integer to a given offset. 3. Write a number within the range [0, 2^32-1] into a 4-byte location. 4. Change to the next offset and repeat. """ ol = Overlay('base.bit') ol.download() sleep(0.2) mmio_base = int(ol.get_ip_addr_base('SEG_mb_bram_ctrl_1_Mem0'),16) mmio_range = int(ol.get_ip_addr_range('SEG_mb_bram_ctrl_1_Mem0'),16) mmio = MMIO(mmio_base, mmio_range) for offset in range(0, 100, general_const.MMIO_WORD_LENGTH): data1 = randint(0, pow(2,32)-1) mmio.write(offset, data1) sleep(0.02) data2 = mmio.read(offset) assert data1==data2, \ 'MMIO read back a wrong random value at offset {}.'.format(offset) mmio.write(offset, 0) sleep(0.02) assert mmio.read(offset)==0, \ 'MMIO read back a wrong fixed value at offset {}.'.format(offset) del ol
class GPIOModulesCTL: def __init__(self): self.overlay = Overlay("SerDesTestOverlay/design_1_wrapper.bit", 0) self.overlay.download() #Multicolor LEDs self.axi_gpio_0_h = MMIO(axi_gpio_0_addr, axi_gpio_range) self.axi_gpio_0_h.write(0x4, 0x0) self.axi_gpio_0_h.write(0x0, 0x0) #SelectIO Interface self.axi_gpio_1_h = MMIO(axi_gpio_1_addr, axi_gpio_range) self.axi_gpio_1_h.write(0x4, 0xFFFFFFFF) #PLL lock indicators self.axi_gpio_2_h = MMIO(axi_gpio_2_addr, axi_gpio_range) self.axi_gpio_2_h.write(0x4, 0xFFFFFFFF) def gpio_0_write(self, val): self.axi_gpio_0_h.write(0x0, val) def gpio_1_read(self): return self.axi_gpio_1_h.read(0x0) def gpio_2_read(self): return self.axi_gpio_2_h.read(0x0)
class MaxLayer(object): def __init__(self, layer, fm, dim, xlnk, batchsize=1): self.layer = layer self.fm = fm self.dim = dim self.xlnk = xlnk self.batchsize = batchsize self.ol = Overlay( os.path.dirname(os.path.realpath(__file__)) + "/bitstream/" + self.layer + ".bit") self.dma = self.ol.axi_dma_0 self.cmaOutMax = [] for b in range(self.batchsize): self.cmaOutMax.append( self.xlnk.cma_array(shape=(self.fm * (self.dim**2), ), dtype=np.float32)) def __call__(self, input): self.ol.download() self.dma.sendchannel.start() self.dma.recvchannel.start() b = 0 while b < self.batchsize: self.dma.recvchannel.transfer(self.cmaOutMax[b]) self.dma.sendchannel.transfer(input[b]) self.dma.sendchannel.wait() self.dma.recvchannel.wait() b += 1 return self.cmaOutMax
class SP_TOOLS: def __init__(self): self.OV = Overlay("Single_Photons/SP_OVERLAY.bit", 0) self.OV.download() ##Initialize pulse counter axi_offset = 0 #Initialize data channels self.PC_DAT = [] global axi_range for i in range(4): self.PC_DAT.append(MMIO(axi_base_addr + (i * axi_range), axi_range)) self.PC_DAT[i].write(ch1_dir, agpi) #ch1 is counts self.PC_DAT[i].write(ch2_dir, agpo) #Ch2 is window self.PC_DAT[i].write(ch2_data, 0xFFFFFFFF) #Initialize utility channels axi_offset = 4 self.PC_UTIL = [] for i in range(4): self.PC_UTIL.append( MMIO(axi_base_addr + ((i + axi_offset) * axi_range), axi_range)) self.PC_UTIL[i].write(ch1_dir, agpo) #Reset self.PC_UTIL[i].write(ch1_data, 0x0) #Hold in reset self.PC_UTIL[i].write(ch2_dir, agpi) #Ready #Initialize trigger controller self.T_UTIL = MMIO(0x41200000, 0x10000) self.T_UTIL.write(ch2_dir, 0x0) self.T_UTIL.write(ch2_data, 0x0) self.T_RDY_UTIL = MMIO(0x41210000, 0x10000) self.T_RDY_UTIL.write(ch1_dir, 0x1) ##Initialize single channel inter-rising_edge detection axi_offset = 8 self.ST_DAT = MMIO(axi_base_addr + axi_offset * axi_range, axi_range) self.ST_DAT.write(ch1_dir, agpi) self.ST_DAT.write(ch2_dir, agpo) self.ST_DAT.write(ch2_data, 0x0) #Hold in reset self.ST_RDY = MMIO(axi_base_addr + (axi_offset + 1) * axi_range, axi_range) self.ST_RDY.write(ch1_dir, agpi) ##Initialize interchannel coincidence timer axi_offset = 10 self.CT_DAT = MMIO(axi_base_addr + axi_offset * axi_range, axi_range) self.CT_DAT.write(ch1_dir, agpi) self.CT_DAT.write(ch2_dir, agpo) self.CT_DAT.write(ch2_data, 0x0) #Hold in reset self.CT_RDY = MMIO(axi_base_addr + (axi_offset + 1) * axi_range, axi_range) self.CT_RDY.write(ch1_dir, agpi) ##Initialize Pulse generator axi_offset = 12 iDC = 0.5 iFREQ = 440.0 ph0, ph1 = self.encode_phase_inc(iFREQ) iDCenc = self.calc_dc_lim(iFREQ, iDC) self.PG_PH = [] self.PG_AUX = [] self.chfreqs = [440.0, 440.0, 440.0, 440.0] self.chdcs = [0.5, 0.5, 0.5, 0.5] self.chdelays = [0, 0, 0, 0] for i in range(4): #Phase increments tap = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) tap.write(ch1_dir, agpo) tap.write(ch2_dir, agpo) tap.write(ch1_data, ph0) tap.write(ch2_data, ph1) self.PG_PH.append(tap) axi_offset += 1 self.chfreqs[i] = 440.0 for i in range(4): #Duty length and delay tdc = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) tdc.write(ch1_dir, agpo) tdc.write(ch1_data, iDCenc) tdc.write(ch2_dir, agpo) tdc.write(ch2_data, 0x0) self.PG_AUX.append(tdc) axi_offset += 1 self.chdcs[i] = 0.5 self.PG_UTIL = MMIO(0x43D40000, 0x10000) #increment load and master reset self.PG_UTIL.write(ch1_dir, agpo) self.PG_UTIL.write(ch2_dir, agpo) self.PG_UTIL.write(ch1_data, 0x0) #SEt loader to 0 self.PG_UTIL.write(ch2_data, 0x0) #Hold in reset #Routine to write initial phase increments self.PG_UTIL.write(ch2_data, 0x1) self.PG_UTIL.write(ch1_data, 0xF) sleep(slt) self.PG_UTIL.write(ch1_data, 0x0) #Channel enable controller self.T_UTIL.write(ch1_dir, 0x0) self.T_UTIL.write(ch1_data, 0xF) #SEt all channels to high impedance axi_offset += 1 self.pg_ch_stat = 0xF #self.PG_UTIL.write(ch2_data,0x0) ##Initialize Time Tagger #initialize detector MMIOs self.TT_DET = [] for i in range(4): temp = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) temp.write(ch1_dir, 0xFFFFFFFF) temp.write(ch2_dir, 0xFFFFFFFF) self.TT_DET.append(temp) axi_offset += 1 #Initialize timeout MMIO self.TT_TIME_OUT = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) self.TT_TIME_OUT.write(ch1_dir, 0x0) self.TT_TIME_OUT.write(ch2_dir, 0x0) self.TT_TIME_OUT.write(ch1_data, 0xFFFFFFFF) self.TT_TIME_OUT.write(ch2_data, 0xFFFF) axi_offset += 1 #Initialize utility print(hex(axi_base_addr + (axi_offset * axi_range))) print(hex(axi_range)) self.TT_UTIL = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) self.TT_UTIL.write(ch1_dir, 0x0) self.TT_UTIL.write(ch2_dir, 0xFFFFFFFF) self.TT_UTIL.write(ch1_data, 0x0) #Hold system in reset axi_offset += 1 ##Initialize IDELAY self.iDD_DATA = [] self.iDD_UTIL = [] for i in range(6): tempdel = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) tempdel.write(ch1_data, 0x0) tempdel.write(ch2_data, 0x0) self.iDD_DATA.append(tempdel) axi_offset += 1 for i in range(6): temputil = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) temputil.write(ch1_data, 0x1) temputil.write(ch2_data, 0x1) self.iDD_UTIL.append((temputil)) axi_offset += 1 ####------------------PHOTON COUNTER---------------------------------------------------#### def pc_set_window( self, window, channels): #Channels is 4 bit integer, window is in seconds m = 0B0001 wval = int(window * TIMER_CLK) if (wval > 0xFFFFFFFF or wval <= 0): print( "Window must be between 34.35973836s and 0, cannot be 0 seconds" ) return for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_DAT[i].write(ch2_data, wval) def pc_wait_for_rdy(self, channel, mode): if mode == 0: if (self.PC_UTIL[channel].read(ch2_data) == 0): while (self.PC_UTIL[channel].read(ch2_data) == 0): pass else: while (self.PC_UTIL[channel].read(ch2_data) == 1): pass else: if (self.T_RDY_UTIL.read(ch1_data) == 0): while (self.T_RDY_UTIL.read(ch1_data) == 0): pass def pc_ex_triggered(self, window): self.pc_set_window(window, 0xF) self.T_UTIL.write(ch2_data, 0x1) self.pc_wait_for_rdy(0, 0) retval = [] for i in range(4): retval.append(self.pc_read_counts(i)) self.T_UTIL.write(ch2_data, 0x0) return retval def pc_ex_trig_stop(self): self.T_UTIL.write(ch2_data, 0x3) for i in range(4): self.PC_DAT[i].write(ch2_data, 0xFFFFFFFF) self.pc_wait_for_rdy(0, 1) retval = [] for i in range(4): retval.append(self.pc_read_counts(i)) self.T_UTIL.write(ch2_data, 0x0) return retval def pc_enable_channels(self, channels): #channels a 4 bit integer for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_UTIL[i].write(ch1_data, 0x1) def pc_disable_channels(self, channels): #Channels a 4 bit integer for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_UTIL[i].write(ch1_data, 0x0) def pc_read_counts(self, channel): return self.PC_DAT[channel].read(ch1_data) ####----------------------------------------------------------------------------------#### ####------------------Single line inter-rising_edge timer-----------------------------#### def st_arm_and_wait(self): self.ST_DAT.write(ch2_data, 0x1) #Enable op = 0 while (self.ST_RDY.read(ch1_data) == 0x0): #Wait for ready pass if (self.ST_RDY.read(ch1_data) == 0x1): op = self.ST_DAT.read(ch1_data) #Read time self.ST_DAT.write(ch2_data, 0x0) return op * (1 / REF_CLK) ####----------------------------------------------------------------------------------#### ####------------------Two channel photon coincidence timer----------------------------#### def ct_arm_and_wait(self): self.CT_DAT.write(ch2_data, 0x1) # Enable op = 0 #print("Armed") while (self.CT_RDY.read(ch1_data) == 0x0): # Wait for ready pass #print("Triggered") if (self.CT_RDY.read(ch1_data) == 0x1): #print("Reading") op = self.CT_DAT.read(ch1_data) # Read time self.CT_DAT.write(ch2_data, 0x0) return op * (1 / REF_CLK) ####---------------------Signal generator---------------------------------------------#### def pg_disable(self): self.PG_UTIL.write(ch2_data, 0x0) def pg_enable(self): self.PG_UTIL.write(ch2_data, 0x1) def pg_enable_channel(self, channel): self.pg_ch_stat = ~(~self.pg_ch_stat | (0B0001 << channel)) self.T_UTIL.write(ch1_data, self.pg_ch_stat) def pg_disable_channel(self, channel): self.pg_ch_stat = self.pg_ch_stat | (0b0001 << channel) self.T_UTIL.write(ch1_data, self.pg_ch_stat) def pg_set_channel_freq(self, channel, freq): nenc = self.encode_phase_inc(2 * freq) self.PG_PH[channel].write(ch1_data, nenc[0]) self.PG_PH[channel].write(ch2_data, nenc[1]) self.PG_UTIL.write(ch1_data, 0xF) sleep(slt) self.PG_UTIL.write(ch1_data, 0x0) newdc = self.calc_dc_lim(freq, self.chdcs[channel]) self.PG_UTIL.write(ch2_data, 0x0) self.PG_AUX[channel].write(ch1_data, newdc) self.PG_AUX[channel].write(ch2_data, self.calc_delay(self.chdelays[channel])) self.PG_UTIL.write(ch2_data, 0x1) self.chfreqs[channel] = freq def pg_set_dc(self, channel, dc): #Dc from 0 to 1 dcenc = self.calc_dc_lim(self.chfreqs[channel], dc) self.PG_UTIL.write(ch2_data, 0x0) self.PG_AUX[channel].write(ch1_data, dcenc) self.PG_UTIL.write(ch2_data, 0x1) self.chdcs[channel] = dc def pg_set_pw(self, channel, pw): pwv = self.calc_delay(pw / 1000) self.PG_UTIL.write(ch2_data, 0x0) self.PG_AUX[channel].write(ch1_data, pwv) self.PG_UTIL.write(ch2_data, 0x1) tlim = REF_CLK / self.chfreqs[channel] self.chdcs[channel] = pwv / tlim def pg_set_delay(self, channel, delay): #Delay in seconds delv = self.calc_delay(delay) self.PG_UTIL.write(ch2_data, 0x0) self.PG_AUX[channel].write(ch2_data, delv) self.chdelays[channel] = delay self.PG_UTIL.write(ch2_data, 0x1) def encode_phase_inc(self, freq): enc = int((freq * 2**PHASE_BIT_DEPTH) / REF_CLK) lsb = enc & 0xFFFFFFFF msb = (enc >> 32) & 0xFFFF return [lsb, msb] def calc_dc_lim(self, freq, dc): #dc from 0 to 1 dc_t = int(REF_CLK / freq) return int(dc_t * dc) def calc_delay(self, delay): return int(delay * REF_CLK) def TT_concat48(self, lsb, msb): retval = (lsb & 0xFFFFFFFF) | ((msb & 0xFFFF) << 32) return retval def TT_slice48(self, xsl): lsb = xsl & 0xFFFFFFFF msb = (xsl >> 32) & 0xFFFF return [lsb, msb] def TT_set_timeout(self, time): tval = time * REF_CLK lsb, msb = self.TT_slice48(int(tval)) self.TT_TIME_OUT.write(ch1_data, lsb) self.TT_TIME_OUT.write(ch2_data, msb) def TT_reset(self): self.TT_UTIL.write(ch1_data, 0b0) def TT_activate(self, timeout): self.TT_set_timeout(timeout) self.TT_UTIL.write(ch1_data, 0b1) def TT_read_times(self): retvals = [] for i in range(4): lsb = self.TT_DET[i].read(ch1_data) msb = self.TT_DET[i].read(ch2_data) retvals.append(self.TT_concat48(lsb, msb)) return retvals def TT_read_states(self): return self.TT_UTIL.read(ch2_data) & 0xF def TT_read_rdy(self): return (self.TT_UTIL.read(ch2_data) >> 4) & 0x1 def TT_proc(self): print("Waiting for data") if (self.TT_read_rdy() == 0): print("1") while (self.TT_read_rdy() == 0): pass else: print("0") while (self.TT_read_rdy() == 1): pass vals = self.TT_read_times() states = self.TT_read_states() return { 'T1': vals[0] * (1 / REF_CLK), 'T2': vals[1] * (1 / REF_CLK), 'T3': vals[2] * (1 / REF_CLK), 'T4': vals[3] * (1 / REF_CLK), 'T1s': (states & 1), 'T2s': ((states >> 1) & 0b1), 'T3s': ((states >> 2) & 0b1), 'T4s': ((states >> 3) & 0b1) } def DD_idelay(self, channel, tap, stage): print("Setting input delay on channel " + str(channel) + " dline tap of " + str(tap) + " with " + str(stage) + " stage(s).") self.iDD_UTIL[channel].write(ch1_data, 0x0) sleep(slt) self.iDD_UTIL[channel].write(ch1_data, 0x1) self.iDD_DATA[channel].write(ch1_data, tap) self.iDD_DATA[channel].write(ch2_data, stage)
def solve(boardstr, seed=12345, zero_padding=False): print('boardstr:') print(boardstr) print('seed:') print(seed) print('') # ボード文字列から X, Y, Z を読んでくる size_x = (ord(boardstr[1]) - ord('0')) * 10 + (ord(boardstr[2]) - ord('0')) size_y = (ord(boardstr[4]) - ord('0')) * 10 + (ord(boardstr[5]) - ord('0')) size_z = (ord(boardstr[7]) - ord('0')) # Overlay 読み込み OL = Overlay('pynqrouter.bit') OL.download() print(OL.ip_dict) print('Overlay loaded!') # MMIO 接続 (pynqrouter) mmio = MMIO(int(PL.ip_dict[IP][0]), int(PL.ip_dict[IP][1])) # MMIO 接続 & リセット (LED) mmio_led = MMIO(int(PL.ip_dict[IP_LED][0]), int(PL.ip_dict[IP_LED][1])) mmio_led.write(0, 0) # 入力データをセット imem = pack(boardstr) for i in range(len(imem)): mmio.write(OFFSET_BOARD + (i * 4), imem[i]) mmio.write(OFFSET_SEED, seed) # スタート # ap_start (0 番地の 1 ビット目 = 1) mmio.write(0, 1) print('Start!') time_start = time.time() # ap_done (0 番地の 2 ビット目 = 2) が立つまで待ってもいいが # done は一瞬だけ立つだけのことがあるから # ap_idle (0 番地の 3 ビット目 = 4) を待ったほうが良い iteration = 0 while (mmio.read(0) & 4) == 0: # 動いてるっぽく見えるようにLチカさせる iteration += 1 if iteration == 10000: mmio_led.write(0, 3) elif 20000 <= iteration: mmio_led.write(0, 12) iteration = 0 # 完了の確認 print('Done!') print('control:', mmio.read(0)) time_done = time.time() elapsed = time_done - time_start print('elapsed:', elapsed) print('') # 状態の取得 status = int(mmio.read(OFFSET_STATUS)) print('status:', status) if status != 0: # 解けなかったらLEDを消す mmio_led.write(0, 0) sys.stderr.write('Cannot solve it!\n') return {'solved': False, 'solution': '', 'elapsed': -1.0} print('Solved!') # 解けたらLEDを全部つける mmio_led.write(0, 15) # 出力 omem = [] for i in range(len(imem)): omem.append(mmio.read(OFFSET_BOARD + (i * 4))) boards = unpack(omem) # 回答の生成 solution = ('SIZE ' + str(size_x) + 'X' + str(size_y) + 'X' + str(size_z) + '\n') for z in range(size_z): solution += ('LAYER ' + str(z + 1) + '\n') for y in range(size_y): for x in range(size_x): if x != 0: solution += ',' i = ((x * MAX_X + y) << BITWIDTH_Z) | z if zero_padding: solution += '{0:0>2}'.format(boards[i]) # 2桁の0詰め else: solution += str(boards[i]) # 普通に表示 solution += '\n' return {'solved': True, 'solution': solution, 'elapsed': elapsed}
#!/usr/bin/python3 from pynq import Overlay from pynq import Xlnk import numpy as np import time xlnk = Xlnk() ol = Overlay("vpu_ddr4_100M.bit") for i in ol.ip_dict: print(i) ol.download() #gpio=ol.axi_gpio_0 #gpio.write(0,0xF); #
class SP_TOOLS: def __init__(self): """Initializes the hardware by first loading and configuring the FPGA with the hardware design and then by creating handles for each AXI GPIO block that allows connection from the processing system to the FPGA fabric. """ #Import FPGA configuration file and download self.OV = Overlay("Single_Photons/SP_OVERLAY.bit", 0) self.OV.download() ##Initialize pulse counter axi_offset = 0 #Initialize data channels self.PC_DAT = [] #Holds all the handles for the data GPIO blocks #Initialize AXI GPIO modules for i in range(4): self.PC_DAT.append( MMIO(axi_base_addr + (axi_offset * axi_range), axi_range)) self.PC_DAT[i].write(ch1_dir, agpi) #ch1 is counts self.PC_DAT[i].write(ch2_dir, agpo) #Ch2 is window self.PC_DAT[i].write(ch2_data, 0xFFFFFFFF) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 #Initialize utility channels self.PC_UTIL = [] #Utility GPIO modules (containing reset signal and for i in range(4): self.PC_UTIL.append( MMIO(axi_base_addr + ((axi_offset) * axi_range), axi_range)) self.PC_UTIL[i].write(ch1_dir, agpo) #Reset self.PC_UTIL[i].write(ch1_data, 0x0) #Hold in reset self.PC_UTIL[i].write(ch2_dir, agpi) #Ready plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 #Initialize trigger controller self.T_UTIL = MMIO(0x41200000, 0x10000) self.T_UTIL.write(ch2_dir, 0x0) self.T_UTIL.write(ch2_data, 0x0) self.T_RDY_UTIL = MMIO(0x41210000, 0x10000) self.T_RDY_UTIL.write(ch1_dir, 0x1) ##Initialize single channel inter-rising_edge detection self.ST_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.ST_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range, axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 ##Initialize interchannel coincidence timer self.CT_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.CT_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range, axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 ##Initialize time tagger self.TT_CONFIG = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info("TT_CONFIG: " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.TT_DATA0 = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info("TT_DATA0: " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.TT_DATA1 = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info("TT_DATA1: " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.TT_DELAY_DATA = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info("TT_DELAY: " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.TT_UTIL = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info("TT_UTIL: " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 ##Initialize Pulse generator iDC = 0.5 #Initial duty cycle and frequency iFREQ = 440.0 ph0, ph1 = self.encode_phase_inc(iFREQ) iDCenc = self.calc_dc_lim(iFREQ, iDC) self.PG_PH = [ ] #AXI GPIO handles for phase increments for each channel self.PG_AUX = [ ] #AXI GPIO handles for duty cycle(ch1) and delay(ch2) of the GPIO block self.chfreqs = [440.0, 440.0, 440.0, 440.0] #Initial frequency settings of each channel self.chdcs = [0.5, 0.5, 0.5, 0.5] #Initial duty cycles of each channel self.chdelays = [0, 0, 0, 0] #Initial delays of each channel for i in range(4): #Duty length and delay tdc = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) tdc.write(ch1_dir, agpo) tdc.write(ch1_data, iDCenc) tdc.write(ch2_dir, agpo) tdc.write(ch2_data, 0x0) self.PG_AUX.append(tdc) plog.info("DC" + str(i) + " " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.chdcs[i] = 0.5 for i in range(4): #Phase increments tap = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) tap.write(ch1_dir, agpo) tap.write(ch2_dir, agpo) tap.write(ch1_data, ph0) tap.write(ch2_data, ph1) self.PG_PH.append(tap) plog.info("PH" + str(i) + " " + hex(axi_base_addr + (axi_offset * axi_range))) axi_offset += 1 self.chfreqs[i] = 440.0 self.PG_UTIL = MMIO(axi_base_addr + (axi_offset * axi_range), 0x10000) #increment load and master reset plog.info("PGUTIL: " + hex(axi_base_addr + (axi_offset * axi_range))) self.PG_UTIL.write(ch1_dir, agpo) self.PG_UTIL.write(ch2_dir, agpo) self.PG_UTIL.write(ch1_data, 0x0) #SEt loader to 0 self.PG_UTIL.write(ch2_data, 0x0) #Hold in reset #Routine to write initial phase increments self.PG_UTIL.write(ch2_data, 0x1) self.PG_UTIL.write(ch1_data, 0xF) sleep(slt) self.PG_UTIL.write(ch1_data, 0x0) #Channel enable controller #The enable controller is a tristate controlled buffer which when disabling the output places the channels into #a high impedance state allowing other devices connected to the same output to assert control (also to prevent the pynq from blowing up if its connected to something that also outputs signals) self.T_UTIL.write(ch1_dir, 0x0) self.T_UTIL.write(ch1_data, 0xF) #SEt all channels to high impedance axi_offset += 1 self.pg_ch_stat = 0xF #self.PG_UTIL.write(ch2_data,0x0) ##Initialize IDELAY self.iDD_DATA = [ ] #AXI GPIO handles for delay data GPIO blocks (which control tap and stages) self.iDD_UTIL = [] #AXI GPIO handles for delay utility (reset) for i in range(6): tempdel = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) tempdel.write(ch1_data, 0x0) tempdel.write(ch2_data, 0x0) self.iDD_DATA.append(tempdel) axi_offset += 1 for i in range(6): temputil = MMIO(axi_base_addr + (axi_offset * axi_range), axi_range) plog.info(hex(axi_base_addr + (axi_offset * axi_range))) temputil.write(ch1_data, 0x1) temputil.write(ch2_data, 0x1) self.iDD_UTIL.append((temputil)) axi_offset += 1 ####------------------PHOTON COUNTER---------------------------------------------------#### def pc_set_window( self, window, channels): #Channels is 4 bit integer, window is in seconds """Sets the pulse counter counting window period Parameters ---------- window : :class:`float` Time to count for (in seconds) channels : :class:`int` Channels to count on (binary encoded) """ m = 0B0001 wval = int(window * TIMER_CLK) if (wval > 0xFFFFFFFF or wval <= 0): plog.error( "Window must be between 34.35973836s and 0, cannot be 0 seconds" ) return for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_DAT[i].write(ch2_data, wval) def pc_wait_for_rdy(self, channel, mode): """Hangs the thread until the counter has data ready to be acquired Parameters ---------- channel : :class:`int` Channel to wait for mode : :class:`int` Mode of operation, 0 for fixed window mode, or 1 for external stop trigger mode """ if mode == 0: #If when the counter stops is defined by time window if (self.PC_UTIL[channel].read(ch2_data) == 0): while (self.PC_UTIL[channel].read(ch2_data) == 0): pass else: while (self.PC_UTIL[channel].read(ch2_data) == 1): pass else: #If when the counter stops is defined by an external stop signal if (self.T_RDY_UTIL.read(ch1_data) == 0): while (self.T_RDY_UTIL.read(ch1_data) == 0): pass def pc_ex_triggered(self, window): """Start counting function for externally supplied start signal Parameters ---------- window : :class:`int` Counting window (in seconds) Returns ------- :class:`list` of `int` List of counts for each channel """ #Set the window of all channels to specified window value and start the counter self.pc_set_window(window, 0xF) self.T_UTIL.write( ch2_data, 0x1 ) #Set the external trigger block to activate the counter once trigger pulse occurs #Wait till the counter finishes counting self.pc_wait_for_rdy(0, 0) retval = [] for i in range(4): retval.append(self.pc_read_counts( i)) #Append each channels counts to output array self.T_UTIL.write(ch2_data, 0x0) return retval def pc_ex_trig_stop(self): """Enables and waits for the pulse counter to stop counting (based off when the stop signal is pulsed) and returns the counts for each channel. Returns ------- :class:`list` of `int` Array of counts for each channel """ # Set the trigger controller to start the counter when the start trigger is acquired # and stop the counter when the stop signal is acquired self.T_UTIL.write(ch2_data, 0x3) #Set the window for all channels to maximum (as window is unknown in this mode and externally defined) for i in range(4): self.PC_DAT[i].write(ch2_data, 0xFFFFFFFF) #Wait until the stop trigger is acquired self.pc_wait_for_rdy(0, 1) retval = [] #Read, store and return all count values as an array for i in range(4): retval.append(self.pc_read_counts(i)) self.T_UTIL.write(ch2_data, 0x0) return retval def pc_enable_channels(self, channels): #channels a 4 bit integer """Enable counting on supplied channels Parameters ---------- channels : :class:`int` Channels to enable counting on (binary encoded) """ #Enable any channel that is indicated by a 1 in the 4 bit integer for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_UTIL[i].write(ch1_data, 0x1) def pc_disable_channels(self, channels): #Channels a 4 bit integer """Disable counting on supplied channels Parameters ---------- channels : :class:`int` Channels to disable counting on (binary encoded) """ #Disable any channel that is indicated by a 1 in the 4 bit integer for i in range(4): if ((0B0001 << i) & channels) != 0: self.PC_UTIL[i].write(ch1_data, 0x0) def pc_read_counts(self, channel): """Read counts on channel specified Parameters ---------- channel : :class:`int` Channel to read counts of (0-3) Returns ------- :class:`int` Number of counts """ return self.PC_DAT[channel].read(ch1_data) ####----------------------------------------------------------------------------------#### ####------------------Single line inter-rising_edge timer-----------------------------#### def st_arm_and_wait(self): """Arm single channel inter-rising_edge timer and hang until time data is ready to be acquired Returns ------- :class:`float` Time between detected rising edges (in seconds) """ self.ST_UTIL.write(ch1_data, 0x1) #Enable while (self.ST_DATA.read(ch2_data) & 0b1) == 0: #Wait for ready pass op = self.ST_DATA.read(ch1_data) / REF_CLK #Read time dels = self.ST_DATA.read( ch2_data) #Read start and finish delay line values #Count the number of ones in both start and finish delay line states, multiply with the delay resolution and add start delay value and subtract stop delay value #to the coarse time op = op + (self.uencode((dels & 0b111111110) >> 1, 8) - self.uencode( (dels & 0b11111111000000000) >> 9, 8)) * FTIME self.ST_UTIL.write(ch1_data, 0x0) return op ####----------------------------------------------------------------------------------#### ####------------------Two channel photon coincidence timer----------------------------#### def ct_arm_and_wait(self, first): """Arm two channel rising edge coincidence timer and hang until time data is ready (On channel 0 and 1) Parameters ---------- first : :class:`int` Defines which channel to listen for start rising edge (0 or 1) Returns ------- :class:`float` Time between rising edges (in seconds) """ #Set which channel the hardware is listening to for the start pulse and take the submodule out of reset enabling it self.CT_UTIL.write(ch2_data, first) self.CT_UTIL.write(ch1_data, 0x1) #Wait for the coincidence time to be ready (waits until the second pulse) while (self.CT_DATA.read(ch2_data) & 0b1) == 0: pass #Read coarse time tm = self.CT_DATA.read(ch1_data) / REF_CLK dels = self.CT_DATA.read( ch2_data ) #Read delay line states including the data ready bit which must be shifted out below #Include fine time offsets with the coarse time tm = tm + (self.uencode((dels & 0b111111110) >> 1, 8) - self.uencode( (dels & 0b11111111000000000) >> 9, 8)) * FTIME self.CT_UTIL.write( ch1_data, 0x0) #Disable coincidence timer by placing it in reset return tm ####---------------------Signal generator---------------------------------------------#### def pg_disable(self): """Disable signal generator, holds the submodule in reset bringing all outputs low """ self.PG_UTIL.write(ch2_data, 0x0) def pg_enable(self): """Enables the signal generator, takes hardware submodule out of reset """ self.PG_UTIL.write(ch2_data, 0x1) def pg_enable_channel(self, channel): """Enable specified channel, takes channel out of tristate high Z mode Parameters ---------- channel : :class:`int` Channel to enable (0-3) """ #As the enable lines are active low, must set the channel specified's place from a 1 to a 0. self.pg_ch_stat = ~(~self.pg_ch_stat | (0B0001 << channel)) self.T_UTIL.write(ch1_data, self.pg_ch_stat) def pg_disable_channel(self, channel): """Disable specified channel, places channel into tristate high Z mode Parameters ---------- channel : :class:`int` Channel to disable (0-3) """ self.pg_ch_stat = self.pg_ch_stat | (0b0001 << channel) self.T_UTIL.write(ch1_data, self.pg_ch_stat) def pg_set_channel_freq(self, channel, freq): """Sets the frequency of the specified channel Parameters ---------- channel : :class:`int` Channel to set frequency of (0-3) freq : :class:`float` Frequency to set channel to (in Hz) """ nenc = self.encode_phase_inc( 2 * freq ) #Calculate the phase increment value required by the DDS Compiler self.PG_PH[channel].write( ch1_data, nenc[0]) #Write LSB(31 downto 0) of total 48 bits to the DDS self.PG_PH[channel].write( ch2_data, nenc[1]) #Write MSB(47 downto 32) of 48 bits to the DDS self.PG_UTIL.write( ch1_data, 0xF) #Enable loading of phase increments to the DDS Compiler sleep(slt) self.PG_UTIL.write(ch1_data, 0x0) #Calculate duty cycle counter limit newdc = self.calc_dc_lim(freq, self.chdcs[channel]) self.PG_UTIL.write(ch2_data, 0x0) #Disable signal generator #Write new settings to the hardware self.PG_AUX[channel].write(ch1_data, newdc) self.PG_AUX[channel].write(ch2_data, self.calc_delay(self.chdelays[channel])) self.PG_UTIL.write(ch2_data, 0x1) #Re-enable signal generator self.chfreqs[ channel] = freq #Synchronzie the host setting of the frequency to the frequency setting on the hardware def pg_set_dc(self, channel, dc): #Dc from 0 to 1 """Sets the duty cycle of the specified channel Parameters ---------- channel : :class:`int` Channel to set the duty cycle of (0-3) dc : :class:`float` Duty cycle to set the specified channel to (0-1) """ #Calculate the duty cycle counter limit from new duty cycle value dcenc = self.calc_dc_lim(self.chfreqs[channel], dc) self.PG_UTIL.write(ch2_data, 0x0) #dsaible signal generator self.PG_AUX[channel].write(ch1_data, dcenc) #WRite new duty cycle counter value self.PG_UTIL.write(ch2_data, 0x1) #Re-enable self.chdcs[ channel] = dc #Sync the host setting of the duty cycle to the duty cycyel setting on hardware def pg_set_pw(self, channel, pw): """Sets the pulse width of the channel specified Parameters ---------- channel : :class:`int` Channel to set pulse width of (0-3) pw : :class:`float` Pulse width to set channel to (in milliseconds) """ pwv = self.calc_delay( pw / 1000) #Calculating duty cycle counter value from time self.PG_UTIL.write(ch2_data, 0x0) #Disable signal generator self.PG_AUX[channel].write( ch1_data, pwv) #Write the new duty cycle counter value to the hardware self.PG_UTIL.write(ch2_data, 0x1) #Re-enable signal generator #Calculate what the new duty cycle of the signal is in 0-1 rather than pulse width and save that as the host setting tlim = REF_CLK / self.chfreqs[channel] self.chdcs[channel] = pwv / tlim def pg_set_delay(self, channel, delay): #Delay in seconds """Sets the delay of the specified channel Parameters ---------- channel : :class:`int` Channel to set delay of (0-3) delay : :class:`float` The delay the specified channel is to be set to(in seconds) """ delv = self.calc_delay( delay ) #Calculate the counter value the delay counter must count upto before enabling the channel self.PG_UTIL.write( ch2_data, 0x0 ) #Disable the signal generator, write the delay value to the delay controller self.PG_AUX[channel].write(ch2_data, delv) self.chdelays[channel] = delay #Save the delay setting self.PG_UTIL.write(ch2_data, 0x1) #Restart the signal generator def encode_phase_inc(self, freq): """Converts a supplied frequency to a phase increment amount that is supplied to the DDS modules to produce the necessary sine wave. Internally used function, should not be called directly. Parameters ---------- freq : :class:`float` Frequency in Hz Returns ------- :class:`list` of :class:`float` 48 bit phase increment, first element is 32 bit LSB, second element is 16 bit MSB :class:`float` is 32 bit LSB :class:`float` is 16 bit MSB """ enc = int( (freq * 2**PHASE_BIT_DEPTH) / REF_CLK ) #Calculate the phase increment of the DDS to produce the required frequency #Split the 48 bit number into 32 and 16 bits lsb = enc & 0xFFFFFFFF msb = (enc >> 32) & 0xFFFF return [lsb, msb] def calc_dc_lim(self, freq, dc): #dc from 0 to 1 """Calculates the count value of the hardware counter where the output changes from high to low after this count value is passed by the hardware counter Parameters ---------- freq : :class:`float` Frequency of the signal currently being emitted. dc : :class:`float` Duty cycle value (0-1) Returns ------- :class:`int` Count value the hardware counter counts up to before switching the output signal from high to low. """ dc_t = int(REF_CLK / freq) return int(dc_t * dc) def calc_delay(self, delay): """Calculates the delay timer count value from a time in seconds Parameters ---------- delay : :class:`float` Delay time in seconds Returns ------- :class:`int` Count limit for delay timer """ return int(delay * REF_CLK) def TT_wait_for_rdy(self): """Wait until time tagger tags each channel or times out (Hangs the thread) """ if (self.TT_UTIL.read(ch2_data) & 0b1) == 0: while (self.TT_UTIL.read(ch2_data) & 0b1) == 0: pass else: while (self.TT_UTIL.read(ch2_data) & 0b1) == 1: pass def TT_set_timeout(self, timeval): """Set the time out of the time tagger Parameters ---------- timeval : :class:`float` Time out in seconds """ tcount = timeval * REF_CLK #Calculate time out counter value self.TT_CONFIG.write( ch1_data, int(tcount)) #Write the new counter value to the time tagger def TT_activate(self, time): """Sets the time out of the time tagger and pulls the time tagger out of reset, activating it Parameters ---------- time : :class:`float` Time out in seconds """ self.TT_set_timeout(time) self.TT_UTIL.write(ch1_data, 0x1) def TT_proc(self): """Time tagger sampling process, waits until time tagger has data ready, then calculates time intervals for each channel from T0 and includes fine times and returns a time interval for each channel and which channels timed out. Returns ------- :class:`dict` A dictionary containing time intervals ('T1'...'T4') and boolean time outs ('T1s'...'T4s') """ self.TT_wait_for_rdy( ) #Wait until the time tagger has finished tagging or has timed out stimet0 = self.uencode( self.TT_DELAY_DATA.read(ch2_data), 8) * FTIME #Calculate the fine time offset of the t0 signal dels = self.TT_DELAY_DATA.read( ch1_data ) #Delay line states for channels 0-3 (Each is concatenated in binary) #Calculating the fine time offsets for each channel stimet1 = self.uencode((dels & 0xFF), 8) * FTIME stimet2 = self.uencode((dels & 0xFF00) >> 8, 8) * FTIME stimet3 = self.uencode((dels & 0xFF0000) >> 16, 8) * FTIME stimet4 = self.uencode((dels & 0xFF000000) >> 24, 8) * FTIME #Include fine time offsets with the coarse times ctime1 = self.TT_DATA0.read(ch1_data) / REF_CLK - stimet1 + stimet0 ctime2 = self.TT_DATA0.read(ch2_data) / REF_CLK - stimet2 + stimet0 ctime3 = self.TT_DATA1.read(ch1_data) / REF_CLK - stimet3 + stimet0 ctime4 = self.TT_DATA1.read(ch2_data) / REF_CLK - stimet4 + stimet0 timeouts = (self.TT_UTIL.read(ch2_data) & 0b11110 ) >> 1 #Read time outs and shift out the data ready line #Store all information in dictionary and return it outdict = { "T1": ctime1, "T2": ctime2, "T3": ctime3, "T4": ctime4, "T1s": timeouts & 0b1, "T2s": (timeouts & 0b10) >> 1, "T3s": (timeouts & 0b100) >> 2, "T4s": (timeouts & 0b1000) >> 3 } return outdict def TT_reset(self): """Puts time tagger into reset, stopping it """ self.TT_UTIL.write(ch1_data, 0x0) def DD_idelay(self, channel, tap, stage): """Sets the input delay of the specified channel by configuring the delay line taps and the number of delay line stages to include Parameters ---------- channel : :class:`int` Channel to delay (0-3) tap : :class:`int` Delay line tap (0-31) stage : :class:`int` Number of delay line stages (0-7) """ plog.info("Setting input delay on channel " + str(channel) + " dline tap of " + str(tap) + " with " + str(stage) + " stage(s).") self.iDD_UTIL[channel].write(ch1_data, 0x0) #Reset and unreset the delay block sleep(slt) self.iDD_UTIL[channel].write(ch1_data, 0x1) self.iDD_DATA[channel].write( ch1_data, tap) #Load the delay line tap for the top stage self.iDD_DATA[channel].write( ch2_data, stage) #Select how many stages are activated below the top stage def uencode(self, val, length): """Calculates the number of binary ones in an integer of specified length Parameters ---------- val : :class:`int` Arbitrary integer to get the number of binary ones from length : :class:`int` Length of the binary integer to include when counting up the ones. Returns ------- :class:`int` The total number of ones within the binary length specified in the specified integer """ cnt = 0 for i in range( length ): #Just counts how many ones in binary there are in the range specified by length if ((val >> i) & 0b1 == 1): cnt += 1 return cnt
from pynq import Overlay ol = Overlay("audiovideo.bit") ol.download() from time import sleep from pynq.video import Frame, vga from IPython.display import Image from pynq.board import Switch import numpy as np import time from pynq.board import Button import os import pylab as p import sys import cv2 from pynq.pmods import PMOD_OLED #oled configuration oled = PMOD_OLED(1) stream = '' # get the Zybo switches switches = [Switch(i) for i in range(4)] # monitor configuration video_out_res_mode = 0 # 640x480 @ 60Hz frame_out_w = 1920 frame_out_h = 1080 # camera configuration
class ConvLayer(object): def __init__(self, layer, fm, dim, xlnk, runFactor=1, batchsize=1): self.layer = layer self.fm = fm self.dim = dim self.xlnk = xlnk self.runFactor = runFactor self.batchsize = batchsize self.COMPUTE = 0 self.CONV_WEIGHT = 1 self.ol = Overlay( os.path.dirname(os.path.realpath(__file__)) + "/bitstream/" + layer + ".bit") self.dma = self.ol.axi_dma_0 self.ip = MMIO(self.ol.ip_dict[self.layer]['phys_addr'], self.ol.ip_dict[self.layer]['addr_range']) self.wBuff = [] self.initWeights() self.cmaOut = [] self.cmaTemp = [] for b in range(self.batchsize): self.cmaOut.append( self.xlnk.cma_array(shape=(self.fm * (self.dim**2), ), dtype=np.float32)) self.allocaCmaTemp() def __call__(self, input): self.ol.download() self.dma.sendchannel.start() self.dma.recvchannel.start() full = [list() for b in range(self.batchsize)] r = 0 while r < self.runFactor: self.ip.write(0x10, self.CONV_WEIGHT) self.ip.write(0x00, 1) # ap_start self.dma.sendchannel.transfer(self.wBuff[r]) self.dma.sendchannel.wait() b = 0 while b < self.batchsize: self.ip.write(0x10, self.COMPUTE) self.ip.write(0x00, 1) # ap_start self.dma.recvchannel.transfer(self.cmaTemp[b][r]) self.dma.sendchannel.transfer(input[b]) self.dma.sendchannel.wait() self.dma.recvchannel.wait() temp = self.cmaTemp[b][r].reshape( (self.dim**2, int(self.fm / self.runFactor))) temp = temp.transpose() temp = temp.reshape( int(self.fm / self.runFactor) * (self.dim**2)) full[b] = np.concatenate((full[b], temp)) b += 1 r += 1 b = 0 while b < self.batchsize: full[b] = full[b].reshape(self.fm, (self.dim**2)).transpose().flatten() np.copyto(self.cmaOut[b], full[b]) b += 1 return self.cmaOut def allocaCmaTemp(self): t = [] for i in range(self.runFactor): t.append( self.xlnk.cma_array(shape=(int(self.fm / self.runFactor) * (self.dim**2), ), dtype=np.float32)) self.cmaTemp.append(t) def initWeights(self): w = np.load( os.path.dirname(os.path.realpath(__file__)) + "/weights/" + self.layer + "/W.npy") b = np.load( os.path.dirname(os.path.realpath(__file__)) + "/weights/" + self.layer + "/b.npy") w = w.reshape((self.runFactor, -1)) b = b.reshape((self.runFactor, -1)) for i in range(self.runFactor): buff = self.xlnk.cma_array(shape=(w[i].size + b[i].size, ), dtype=np.float32) np.concatenate((w[i], b[i]), out=buff) self.wBuff.append(buff)
class cv2pynq(): MAX_WIDTH = 1920 MAX_HEIGHT = 1080 def __init__(self, load_overlay=True): #self.bitstream_name = None self.bitstream_name = "opencv.bit" self.bitstream_path = os.path.join(CV2PYNQ_BIT_DIR, self.bitstream_name) self.ol = Overlay(self.bitstream_path) self.ol.download() self.ol.reset() self.img_filters = self.ol.image_filters self.dmaOut = self.img_filters.axi_dma_0.sendchannel self.dmaIn = self.img_filters.axi_dma_0.recvchannel self.dmaOut.stop() self.dmaIn.stop() self.dmaIn.start() self.dmaOut.start() self.filter2DType = -1 # filter types: SobelX=0, SobelY=1, ScharrX=2, ScharrY=3, Laplacian1=4, Laplacian3=5 self.filter2D_5Type = -1 # filter types: SobelX=0, SobelY=1, Laplacian5=4 self.f2D = self.img_filters.filter2D_hls_0 self.f2D.reset() self.f2D_5 = self.img_filters.filter2D_hls_5_0 self.f2D_5.reset() def close(self): self.dmaOut.stop() self.dmaIn.stop() def Sobel(self, src, ddepth, dx, dy, dst, ksize): if (ksize == 3): self.f2D.rows = src.shape[0] self.f2D.columns = src.shape[1] self.f2D.channels = 1 if (dx == 1) and (dy == 0): if self.filter2DType != 0: self.filter2DType = 0 self.f2D.r1 = 0x000100ff #[-1 0 1] self.f2D.r2 = 0x000200fe #[-2 0 2] self.f2D.r3 = 0x000100ff #[-1 0 1] elif (dx == 0) and (dy == 1): if self.filter2DType != 1: self.filter2DType = 1 self.f2D.r1 = 0x00fffeff #[-1 -2 -1] self.f2D.r2 = 0x00000000 #[ 0 0 0] self.f2D.r3 = 0x00010201 #[ 1 2 1] else: raise RuntimeError("Incorrect dx dy configuration") self.img_filters.select_filter(0) self.f2D.start() return self.filter2D(src, dst) else: #ksize == 5 self.f2D_5.rows = src.shape[0] self.f2D_5.columns = src.shape[1] if (dx == 1) and (dy == 0): if self.filter2D_5Type != 0: self.filter2D_5Type = 0 self.f2D_5.par_V = bytes([ \ #-1, -2, 0, 2, 1, 0xff, 0xfe, 0x00, 0x02, 0x01, \ #-4, -8, 0, 8, 4, 0xfc, 0xf8, 0x00, 0x08, 0x04, \ #-6, -12, 0, 12, 6, 0xfa, 0xf4, 0x00, 0x0c, 0x06, \ #-4, -8, 0, 8, 4, 0xfc, 0xf8, 0x00, 0x08, 0x04, \ #-1, -2, 0, 2, 1, 0xff, 0xfe, 0x00, 0x02, 0x01, \ 0,0,0]) #fill up to allign with 4 elif (dx == 0) and (dy == 1): if self.filter2D_5Type != 1: self.filter2D_5Type = 1 self.f2D_5.par_V = bytes([ \ #-1, -4, -6, -4, -1, 0xff, 0xfc, 0xfa, 0xfc, 0xff, \ #-2, -8, -12, -8, -2, 0xfe, 0xf8, 0xf4, 0xf8, 0xfe, \ # 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, \ # 2, 8, 12, 8, 2, 0x02, 0x08, 0x0c, 0x08, 0x02, \ # 1, 4, 6, 4, 1, 0x01, 0x04, 0x06, 0x04, 0x01, \ 0,0,0]) #fill up to allign with 4 else: raise RuntimeError("Incorrect dx dy configuration") self.img_filters.select_filter(1) self.f2D_5.start() return self.filter2D(src, dst) def Laplacian(self, src, ddepth, dst, ksize): if ksize == 5: self.f2D_5.rows = src.shape[0] self.f2D_5.columns = src.shape[1] if self.filter2D_5Type != 4: self.filter2D_5Type = 4 # "Laplacian_5" self.f2D_5.par_V = bytes([ \ #2, 4, 4, 4, 2, 0x02, 0x04, 0x04, 0x04, 0x02, \ #4, 0, -8, 0, 4, 0x04, 0x00, 0xf8, 0x00, 0x04, \ #4, -8, -24, -8, 4, 0x04, 0xf8, 0xe8, 0xf8, 0x04, \ #4, 0, -8, 0, 4, 0x04, 0x00, 0xf8, 0x00, 0x04, \ #2, 4, 4, 4, 2, 0x02, 0x04, 0x04, 0x04, 0x02, \ 0,0,0]) #fill up to allign with 4 self.img_filters.select_filter(1) self.f2D_5.start() return self.filter2D(src, dst) else: #ksize 1 or 3 self.f2D.rows = src.shape[0] self.f2D.columns = src.shape[1] self.f2D.channels = 1 if ksize == 1: if (self.filter2DType != 4): self.filter2DType = 4 # "Laplacian_1" self.f2D.r1 = 0x00000100 #[ 0 1 0] self.f2D.r2 = 0x0001fc01 #[ 1 -4 1] self.f2D.r3 = 0x00000100 #[ 0 1 0] elif ksize == 3: if (self.filter2DType != 5): self.filter2DType = 5 # "Laplacian_3" self.f2D.r1 = 0x00020002 #[ 2 0 2] self.f2D.r2 = 0x0000f800 #[ 0 -8 0] self.f2D.r3 = 0x00020002 #[ 2 0 2] self.img_filters.select_filter(0) self.f2D.start() return self.filter2D(src, dst) def filter2D(self, src, dst): if hasattr(src, 'physical_address') and hasattr( dst, 'physical_address'): self.dmaIn.transfer(dst) self.dmaOut.transfer(src) self.dmaIn.wait() return dst
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ############################################################################### print("Running testXfFilter2D.py ...") print("Loading overlay") from pynq import Overlay bs = Overlay( "/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2filter2D.bit") bs.download() print("Loading xlnk") from pynq import Xlnk Xlnk.set_allocator_library( '/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2filter2D.so') mem_manager = Xlnk() import pynq_cv.overlays.xv2filter2D as xv2 import numpy as np import cv2 import time import OpenCVUtils as cvu print("Loading image ../images/bigBunny_1080.png")
# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of [project] nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from pynq import Overlay o = Overlay("bismo.bit") o.download()
import time from pynq import Overlay #import numpy as np from pynq import Xlnk M = 200 N = 200 xlnk = Xlnk(); overlay = Overlay('/home/xilinx/pynq/overlays/HMM_v4/HMM_v4_4.bit') overlay.download() HMM_test = overlay.HMM_Scoring_0 arr_m=xlnk.cma_array(shape=(200,),cacheable=0,dtype=int) arr_n=xlnk.cma_array(shape=(200,),cacheable=0,dtype=int) arr_x=xlnk.cma_array(shape=(200,),cacheable=0,dtype=int) s1 = "gcgagcgaactgcggatagttacactaacacacgaggcacgtggttgggagttacggccatgcaatggatagctcctgcatgatcggttattatacagcccattttgggcgccttccaaaggatctacttatcagaaggggtggtgccgcataactctgaccggtgggcgtagtcatagcagacttttgccgggaacgca" s2 = "tggtccatctgcttggtggcagccgcaagatgccaattattggcgcggtcgacggggctgctatctgaatatcatatggtcttcacggagacaggaacttagcaaggtactaatcccacgcaaagtctttttttcaaaaatccagtctagtcctattatatatcctcggaaaacggtattaggacatcgggtacattcta" s3 = "tttattgtttttgatctcgcgtctcaaagtagctccgacacacaagcggcccttggagactgctcccgagtgcctaggggcatttggtacaaggcggttataaaacgacgacctttccccttagtgcacctgggcaggctcacaccattcctccaccgtgtgtattatttgaggggaaggattctcctgtggcggctctt" s4 = "tcaggacccaaggaggtatcaagattggaagattgtctccaggttctataggcaaaatgcaccgccctcaacggccagatgccggccgcagacttagatatgaatagaatcgggtcaagctctgctacatagattctcctccgtgctcgataactgccggagtttacgcgataagattagcggcactcttcgctgggacc" arr1 = list(s1) arr2 = list(s2) arr3 = list(s3) b1 = {} b2 = {} b3 = {} arr1 = [w.replace('a', '1')for w in arr1] arr1 = [w.replace('c', '2') for w in arr1] arr1 = [w.replace('g', '3') for w in arr1] arr1 = [w.replace('t', '4') for w in arr1] arr2 = [x.replace('a', '1')for x in arr2]
class cv2pynq(): MAX_WIDTH = 1920 MAX_HEIGHT = 1080 def __init__(self, load_overlay=True): self.bitstream_name = None self.bitstream_name = "cv2pynq03.bit" self.bitstream_path = os.path.join(CV2PYNQ_BIT_DIR, self.bitstream_name) self.ol = Overlay(self.bitstream_path) self.ol.download() self.ol.reset() self.xlnk = Xlnk() self.partitions = 10 #split the cma into partitions for pipelined transfer self.cmaPartitionLen = self.MAX_HEIGHT * self.MAX_WIDTH / self.partitions self.listOfcma = [ self.xlnk.cma_array(shape=(int(self.MAX_HEIGHT / self.partitions), self.MAX_WIDTH), dtype=np.uint8) for i in range(self.partitions) ] self.img_filters = self.ol.image_filters self.dmaOut = self.img_filters.axi_dma_0.sendchannel self.dmaIn = self.img_filters.axi_dma_0.recvchannel self.dmaOut.stop() self.dmaIn.stop() self.dmaIn.start() self.dmaOut.start() self.filter2DType = -1 # filter types: SobelX=0, SobelY=1, ScharrX=2, ScharrY=3, Laplacian1=4, Laplacian3=5 self.filter2D_5Type = -1 # filter types: SobelX=0, SobelY=1, Laplacian5=4 self.filter2DfType = -1 # filter types: blur=0, GaussianBlur=1 self.ffi = FFI() self.f2D = self.img_filters.filter2D_hls_0 self.f2D.reset() self.f2D_5 = self.img_filters.filter2D_hls_5_0 self.f2D_5.reset() self.f2D_f = self.img_filters.filter2D_f_0 self.f2D_f.reset() self.erodeIP = self.img_filters.erode_hls_0 self.erodeIP.reset() self.dilateIP = self.img_filters.dilate_hls_0 self.dilateIP.reset() self.cmaBuffer_0 = self.xlnk.cma_array(shape=(self.MAX_HEIGHT, self.MAX_WIDTH), dtype=np.uint8) self.cmaBuffer0 = self.cmaBuffer_0.view(self.ContiguousArrayCv2pynq) self.cmaBuffer0.init(self.cmaBuffer_0) self.cmaBuffer_1 = self.xlnk.cma_array(shape=(self.MAX_HEIGHT, self.MAX_WIDTH), dtype=np.uint8) self.cmaBuffer1 = self.cmaBuffer_1.view(self.ContiguousArrayCv2pynq) self.cmaBuffer1.init(self.cmaBuffer_1) self.cmaBuffer_2 = self.xlnk.cma_array( shape=(self.MAX_HEIGHT * 4, self.MAX_WIDTH), dtype=np.uint8) # *4 for CornerHarris return self.cmaBuffer2 = self.cmaBuffer_2.view(self.ContiguousArrayCv2pynq) self.cmaBuffer2.init(self.cmaBuffer_2) self.CannyIP = self.img_filters.canny_edge_0 self.CannyIP.reset() #self.cornerHarrisIP = self.img_filters.CornerHarris_hls_0 #self.cornerHarrisIP.reset() def close(self): #self.dmaOut.stop() #self.dmaIn.stop() self.cmaBuffer_0.close() self.cmaBuffer_1.close() self.cmaBuffer_2.close() for cma in self.listOfcma: cma.close() def Sobel(self, src, ddepth, dx, dy, dst, ksize): if (ksize == 3): self.f2D.rows = src.shape[0] self.f2D.columns = src.shape[1] self.f2D.channels = 1 if (dx == 1) and (dy == 0): if self.filter2DType != 0: self.filter2DType = 0 self.f2D.r1 = 0x000100ff #[-1 0 1] self.f2D.r2 = 0x000200fe #[-2 0 2] self.f2D.r3 = 0x000100ff #[-1 0 1] elif (dx == 0) and (dy == 1): if self.filter2DType != 1: self.filter2DType = 1 self.f2D.r1 = 0x00fffeff #[-1 -2 -1] self.f2D.r2 = 0x00000000 #[ 0 0 0] self.f2D.r3 = 0x00010201 #[ 1 2 1] else: raise RuntimeError("Incorrect dx dy configuration") self.img_filters.select_filter(1) self.f2D.start() return self.filter2D(src, dst) else: #ksize == 5 self.f2D_5.rows = src.shape[0] self.f2D_5.columns = src.shape[1] if (dx == 1) and (dy == 0): if self.filter2D_5Type != 0: self.filter2D_5Type = 0 self.f2D_5.par_V = bytes([ \ #-1, -2, 0, 2, 1, 0xff, 0xfe, 0x00, 0x02, 0x01, \ #-4, -8, 0, 8, 4, 0xfc, 0xf8, 0x00, 0x08, 0x04, \ #-6, -12, 0, 12, 6, 0xfa, 0xf4, 0x00, 0x0c, 0x06, \ #-4, -8, 0, 8, 4, 0xfc, 0xf8, 0x00, 0x08, 0x04, \ #-1, -2, 0, 2, 1, 0xff, 0xfe, 0x00, 0x02, 0x01, \ 0,0,0]) #fill up to allign with 4 elif (dx == 0) and (dy == 1): if self.filter2D_5Type != 1: self.filter2D_5Type = 1 self.f2D_5.par_V = bytes([ \ #-1, -4, -6, -4, -1, 0xff, 0xfc, 0xfa, 0xfc, 0xff, \ #-2, -8, -12, -8, -2, 0xfe, 0xf8, 0xf4, 0xf8, 0xfe, \ # 0, 0, 0, 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, \ # 2, 8, 12, 8, 2, 0x02, 0x08, 0x0c, 0x08, 0x02, \ # 1, 4, 6, 4, 1, 0x01, 0x04, 0x06, 0x04, 0x01, \ 0,0,0]) #fill up to allign with 4 else: raise RuntimeError("Incorrect dx dy configuration") self.img_filters.select_filter(5) self.f2D_5.start() return self.filter2D(src, dst) def Scharr(self, src, ddepth, dx, dy, dst): self.f2D.rows = src.shape[0] self.f2D.columns = src.shape[1] self.f2D.channels = 1 if (dx == 1) and (dy == 0): if self.filter2DType != 2: self.filter2DType = 2 self.f2D.r1 = 0x000300fd #[-3 0 3] self.f2D.r2 = 0x000a00f6 #[-10 0 10] self.f2D.r3 = 0x000300fd #[-3 0 3] elif (dx == 0) and (dy == 1): if self.filter2DType != 3: self.filter2DType = 3 self.f2D.r1 = 0x00fdf6fd #[-3 -10 -3] self.f2D.r2 = 0x00000000 #[ 0 0 0] self.f2D.r3 = 0x00030a03 #[ 3 10 3] else: raise RuntimeError("Incorrect dx dy configuration") self.img_filters.select_filter(1) self.f2D.start() return self.filter2D(src, dst) def Laplacian(self, src, ddepth, dst, ksize): if ksize == 5: self.f2D_5.rows = src.shape[0] self.f2D_5.columns = src.shape[1] if self.filter2D_5Type != 4: self.filter2D_5Type = 4 # "Laplacian_5" self.f2D_5.par_V = bytes([ \ #2, 4, 4, 4, 2, 0x02, 0x04, 0x04, 0x04, 0x02, \ #4, 0, -8, 0, 4, 0x04, 0x00, 0xf8, 0x00, 0x04, \ #4, -8, -24, -8, 4, 0x04, 0xf8, 0xe8, 0xf8, 0x04, \ #4, 0, -8, 0, 4, 0x04, 0x00, 0xf8, 0x00, 0x04, \ #2, 4, 4, 4, 2, 0x02, 0x04, 0x04, 0x04, 0x02, \ 0,0,0]) #fill up to allign with 4 self.img_filters.select_filter(5) self.f2D_5.start() return self.filter2D(src, dst) else: #ksize 1 or 3 self.f2D.rows = src.shape[0] self.f2D.columns = src.shape[1] self.f2D.channels = 1 if ksize == 1: if (self.filter2DType != 4): self.filter2DType = 4 # "Laplacian_1" self.f2D.r1 = 0x00000100 #[ 0 1 0] self.f2D.r2 = 0x0001fc01 #[ 1 -4 1] self.f2D.r3 = 0x00000100 #[ 0 1 0] elif ksize == 3: if (self.filter2DType != 5): self.filter2DType = 5 # "Laplacian_3" self.f2D.r1 = 0x00020002 #[ 2 0 2] self.f2D.r2 = 0x0000f800 #[ 0 -8 0] self.f2D.r3 = 0x00020002 #[ 2 0 2] self.img_filters.select_filter(1) self.f2D.start() return self.filter2D(src, dst) def blur(self, src, ksize, dst): self.f2D_f.rows = src.shape[0] self.f2D_f.columns = src.shape[1] if (self.filter2DfType != 0): self.filter2DfType = 0 #blur mean = self.floatToFixed(1 / 9, cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r11 = mean self.f2D_f.r12 = mean self.f2D_f.r13 = mean self.f2D_f.r21 = mean self.f2D_f.r22 = mean self.f2D_f.r23 = mean self.f2D_f.r31 = mean self.f2D_f.r32 = mean self.f2D_f.r33 = mean self.img_filters.select_filter(2) self.f2D_f.start() return self.filter2D(src, dst) def GaussianBlur(self, src, ksize, sigmaX, sigmaY, dst): self.f2D_f.rows = src.shape[0] self.f2D_f.columns = src.shape[1] if (self.filter2DfType != 1): self.filter2DfType = 1 #GaussianBlur if (sigmaX <= 0): sigmaX = 0.3 * ((ksize[0] - 1) * 0.5 - 1) + 0.8 if (sigmaY <= 0): sigmaY = sigmaX kX = cv2.getGaussianKernel(3, sigmaX, ktype=cv2.CV_32F) #kernel X kY = cv2.getGaussianKernel(3, sigmaY, ktype=cv2.CV_32F) #kernel Y self.f2D_f.r11 = self.floatToFixed(kY[0] * kX[0], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r12 = self.floatToFixed(kY[0] * kX[1], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r13 = self.floatToFixed(kY[0] * kX[2], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r21 = self.floatToFixed(kY[1] * kX[0], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r22 = self.floatToFixed(kY[1] * kX[1], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r23 = self.floatToFixed(kY[1] * kX[2], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r31 = self.floatToFixed(kY[2] * kX[0], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r32 = self.floatToFixed(kY[2] * kX[1], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.f2D_f.r33 = self.floatToFixed(kY[2] * kX[2], cv2pynqDriverFilter2D_f.K_FP_W, cv2pynqDriverFilter2D_f.K_FP_F) self.img_filters.select_filter(2) self.f2D_f.start() return self.filter2D(src, dst) def erode(self, src, kernel, dst, iterations, mode): self.img_filters.select_filter(3) return self.erodeDilateKernel(src, kernel, dst, iterations, mode, self.erodeIP) def dilate(self, src, kernel, dst, iterations, mode): self.img_filters.select_filter(4) return self.erodeDilateKernel(src, kernel, dst, iterations, mode, self.dilateIP) def Canny(self, src, threshold1, threshold2, dst): self.img_filters.select_filter(0) self.CannyIP.rows = src.shape[0] self.CannyIP.columns = src.shape[1] self.CannyIP.threshold1 = threshold1 self.CannyIP.threshold2 = threshold2 self.CannyIP.start() if hasattr(src, 'physical_address') and hasattr( dst, 'physical_address'): self.dmaIn.transfer(dst) self.dmaOut.transfer(src) self.dmaIn.wait() return dst self.cmaBuffer1.nbytes = src.nbytes self.dmaIn.transfer(self.cmaBuffer1) if hasattr(src, 'physical_address'): self.dmaOut.transfer(src) else: self.cmaBuffer0.nbytes = src.nbytes self.copyNto(self.cmaBuffer0, src, src.nbytes) self.dmaOut.transfer(self.cmaBuffer0) self.dmaIn.wait() ret = np.ndarray(src.shape, src.dtype) self.copyNto(ret, self.cmaBuffer1, ret.nbytes) return ret def filter2D(self, src, dst): if dst is None: self.cmaBuffer1.nbytes = src.nbytes elif hasattr(src, 'physical_address') and hasattr( dst, 'physical_address'): self.dmaIn.transfer(dst) self.dmaOut.transfer(src) self.dmaIn.wait() return dst if hasattr(src, 'physical_address'): self.dmaIn.transfer(self.cmaBuffer1) self.dmaOut.transfer(src) self.dmaIn.wait() else: #pipeline the copy to contiguous memory and filter calculation in hardware if src.nbytes < 184800: #440x420 self.partitions = 1 elif src.nbytes < 180000: #600x300 self.partitions = 2 elif src.nbytes < 231200: #680x340 self.partitions = 4 else: self.partitions = 8 self.cmaBuffer1.nbytes = src.nbytes self.dmaIn.transfer(self.cmaBuffer1) chunks_len = int(src.nbytes / (self.partitions)) self.cmaBuffer0.nbytes = chunks_len self.cmaBuffer2.nbytes = chunks_len #self.copyNto(src,self.cmaBuffer0,chunks_len) self.copyNto(self.cmaBuffer0, src, chunks_len) for i in range(1, self.partitions): if i % 2 == 1: while not self.dmaOut.idle and not self.dmaOut._first_transfer: pass self.dmaOut.transfer(self.cmaBuffer0) #self.copyNtoOff(src ,self.cmaBuffer2,chunks_len, i*chunks_len, 0) self.copyNtoOff(self.cmaBuffer2, src, chunks_len, 0, i * chunks_len) else: while not self.dmaOut.idle and not self.dmaOut._first_transfer: pass self.dmaOut.transfer(self.cmaBuffer2) #self.copyNtoOff(src ,self.cmaBuffer0,chunks_len, i*chunks_len, 0) self.copyNtoOff(self.cmaBuffer0, src, chunks_len, 0, i * chunks_len) while not self.dmaOut.idle and not self.dmaOut._first_transfer: pass self.dmaOut.transfer(self.cmaBuffer2) rest = src.nbytes % self.partitions if rest > 0: #cleanup any remaining data and send it to HW #self.copyNtoOff(src ,self.cmaBuffer0,chunks_len, self.partitions*chunks_len, 0) self.copyNtoOff(self.cmaBuffer0, src, chunks_len, 0, self.partitions * chunks_len) while not self.dmaOut.idle and not self.dmaOut._first_transfer: pass self.dmaOut.transfer(self.cmaBuffer0) rest -= chunks_len self.dmaIn.wait() ret = np.ndarray(src.shape, src.dtype) self.copyNto(ret, self.cmaBuffer1, ret.nbytes) return ret def floatToFixed(self, f, total_bits, fract_bits): """convert float f to a signed fixed point with #total_bits and #frac_bits after the point""" fix = int((abs(f) * (1 << fract_bits))) if (f < 0): fix += 1 << total_bits - 1 return fix def erodeDilateKernel(self, src, kernel, dst, iterations, mode, filter): filter.mode = mode filter.rows = src.shape[0] filter.columns = src.shape[1] if hasattr(src, 'physical_address') and hasattr( dst, 'physical_address'): filter.start() if iterations > 1: self.dmaIn.transfer(self.cmaBuffer1) else: self.dmaIn.transfer(dst) self.dmaOut.transfer(src) self.dmaIn.wait() self.cmaBuffer2.nbytes = src.nbytes #buffer = self.xlnk.cma_array(src.shape, dtype=np.uint8) for i in range(2, iterations + 1): filter.start() if i % 2 == 0: self.dmaIn.transfer(self.cmaBuffer2) if i != iterations: #avoid copy after last iteration self.dmaOut.transfer(self.cmaBuffer1) else: self.dmaOut.transfer(dst) else: self.dmaIn.transfer(self.cmaBuffer1) if i != iterations: self.dmaOut.transfer(self.cmaBuffer2) else: self.dmaOut.transfer(dst) self.dmaIn.wait() return dst self.cmaBuffer0.nbytes = src.nbytes self.cmaBuffer1.nbytes = src.nbytes filter.start() self.dmaIn.transfer(self.cmaBuffer1) if hasattr(src, 'physical_address'): self.dmaOut.transfer(src) else: self.copyNto(self.cmaBuffer0, src, src.nbytes) #np.copyto(srcBuffer,src) self.dmaOut.transfer(self.cmaBuffer0) self.dmaIn.wait() self.cmaBuffer2.nbytes = src.nbytes #buffer = self.xlnk.cma_array(src.shape, dtype=np.uint8) for i in range(2, iterations + 1): filter.start() if i % 2 == 0: self.dmaIn.transfer(self.cmaBuffer2) self.dmaOut.transfer(self.cmaBuffer1) else: self.dmaIn.transfer(self.cmaBuffer1) self.dmaOut.transfer(self.cmaBuffer2) self.dmaIn.wait() ret = np.ndarray(src.shape, src.dtype) if iterations % 2 == 1: self.copyNto(ret, self.cmaBuffer1, ret.nbytes) else: self.copyNto(ret, self.cmaBuffer2, ret.nbytes) return ret '''def cornerHarris(self, src, k, dst): self.img_filters.select_filter(5) self.cornerHarrisIP.rows = src.shape[0] self.cornerHarrisIP.columns = src.shape[1] self.cornerHarrisIP.start() if hasattr(src, 'physical_address') and hasattr(dst, 'physical_address') and (dst.nbytes == src.nbytes*4): self.dmaIn.transfer(dst) self.dmaOut.transfer(src) self.dmaIn.wait() return dst self.cmaBuffer2.nbytes = src.nbytes*4 self.dmaIn.transfer(self.cmaBuffer2) if hasattr(src, 'physical_address') : self.dmaOut.transfer(src) else: self.cmaBuffer0.nbytes = src.nbytes self.copyNto(self.cmaBuffer0,src,src.nbytes) self.dmaOut.transfer(self.cmaBuffer0) self.dmaIn.wait() ret = np.ndarray(src.shape,np.float32) self.copyNto(ret,self.cmaBuffer2,ret.nbytes) return ret''' def copyNto(self, dst, src, N): dstPtr = self.ffi.cast("uint8_t *", self.ffi.from_buffer(dst)) srcPtr = self.ffi.cast("uint8_t *", self.ffi.from_buffer(src)) self.ffi.memmove(dstPtr, srcPtr, N) def copyNtoOff(self, dst, src, N, dstOffset, srcOffset): dstPtr = self.ffi.cast("uint8_t *", self.ffi.from_buffer(dst)) srcPtr = self.ffi.cast("uint8_t *", self.ffi.from_buffer(src)) dstPtr += dstOffset srcPtr += srcOffset self.ffi.memmove(dstPtr, srcPtr, N) class ContiguousArrayCv2pynq(ContiguousArray): def init(self, cmaArray): self._nbytes = cmaArray.nbytes self.physical_address = cmaArray.physical_address self.cacheable = cmaArray.cacheable # overwrite access to nbytes with own function @property def nbytes(self): return self._nbytes @nbytes.setter def nbytes(self, value): self._nbytes = value