Exemplo n.º 1
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
Exemplo n.º 2
0
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
    
Exemplo n.º 3
0
import os
import pytest
from pynq import PL
from pynq import Overlay
from pynq import Clocks
from pynq.pl import BS_BOOT
from pynq.ps import DEFAULT_CLK_MHZ

__author__ = "Yun Rock Qu"
__copyright__ = "Copyright 2016, Xilinx"
__email__ = "*****@*****.**"

bitfile1 = BS_BOOT
bitfile2 = PL.bitfile_name
ol1 = Overlay(bitfile1)
ol2 = Overlay(bitfile2)

cpu_mhz = 0
bitfile1_fclk0_mhz = DEFAULT_CLK_MHZ
bitfile1_fclk1_mhz = DEFAULT_CLK_MHZ
bitfile1_fclk2_mhz = DEFAULT_CLK_MHZ
bitfile1_fclk3_mhz = DEFAULT_CLK_MHZ
bitfile2_fclk0_mhz = DEFAULT_CLK_MHZ
bitfile2_fclk1_mhz = DEFAULT_CLK_MHZ
bitfile2_fclk2_mhz = DEFAULT_CLK_MHZ
bitfile2_fclk3_mhz = DEFAULT_CLK_MHZ


@pytest.mark.run(order=2)
def test_overlay():
Exemplo n.º 4
0
print("Xlnk buffer x-values: ", px_buffer)
print("Xlnk buffer y-values: ", py_buffer)
print("Xlnk buffer Z-values: ", pz_buffer)

#reset the ADC
adc.reset()

# Now Transfer the contents of the buffers to the Custom IPs in PL via AXI DMA
# X-Values to X-Function, Y-Values to Y Function, Z-Values to Z-Function

#First delete the base overlay
del ol

#load the overlay for the custom streaming XYZ-values IP built and tested in TEST D
from pynq import Overlay
overlay = Overlay('/home/xilinx/pynq/overlays/stream_xyz/stream_xyz.bit')

#Test the overlay
#overlay? #returns the IP blocks contained in the Overlay which were built for each function
#overlay.ip_dict # returns full path to each dma x,y,z = x_function.dmaz, y_function.dmay, z_function.dmaz

#assign the DMAs which are the IPs built to recive and operate on the incomming buffer data
dma_x = overlay.x_function.dmax
dma_y = overlay.y_function.dmay
dma_z = overlay.z_function.dmaz

# Trigger the DMA transfer of the samples from buffers to the PL

#set up send channel xyz
dma_x.sendchannel.transfer(px_buffer)
dma_y.sendchannel.transfer(py_buffer)
Exemplo n.º 5
0
from pynq import Overlay
from os import path

current_dir = path.abspath(path.dirname(__file__))
bitfile = path.join(current_dir, "stable.bit")

o = Overlay(bitfile)
o.download()
Exemplo n.º 6
0
    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("SP_OVERLAY.bit", 0)
        self.OV.download()
        axi_offset = 0
        ##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
        #43c4
        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
        #43c8
        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)))
        axi_offset += 1
        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)
        #43c9
        ##Initialize IDELAY
        self.DELAY_TAPS = MMIO(axi_base_addr + (axi_offset * axi_range),
                               0x10000)

        plog.info("IDELAY: " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43ca

        ##Initialize pulse counter
        #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("PCDAT" + str(i) + " -- " +
                      hex(axi_base_addr + (axi_offset * axi_range)))
            axi_offset += 1
        #43ce
        #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("PCUT" + str(i) + " -- " + hex(axi_base_addr +
                                                     (axi_offset * axi_range)))
            axi_offset += 1
        #43d2
        #Initialize trigger controller
        self.T_UTIL = MMIO(0x41210000, 0x10000)
        self.T_UTIL.write(ch2_dir, 0x0)
        self.T_UTIL.write(ch2_data, 0x0)
        self.T_RDY_UTIL = MMIO(0x41200000, 0x10000)
        self.T_RDY_UTIL.write(ch1_dir, 0x1)
        ##Initialize single channel inter-rising_edge detection
        self.ST_FIFO_BUFFER = []
        self.ST_loaded_count = 0
        for i in range(FIFO_DEPTH):
            self.ST_FIFO_BUFFER.append(0)
        self.ST_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range)
        plog.info("STDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.ST_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.ST_UTIL.write(ch1_data, 0x0)
        plog.info("STUTIL -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        ##Initialize interchannel coincidence timer
        self.CT_FIFO_BUFFER = []
        self.CT_loaded_count = 0
        for i in range(FIFO_DEPTH):
            self.CT_FIFO_BUFFER.append(0)
        self.CT_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range)
        plog.info("CTDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.CT_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.CT_UTIL.write(ch1_data, self.CT_UTIL.read(0x0) & 0b110)
        plog.info("CTUTIL -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43d6
        ##Initialize time tagger
        self.TT_FIFO_BUFFER = []
        for i in range(FIFO_DEPTH):
            self.TT_FIFO_BUFFER.append(0)
        self.TT_loaded_count = 0
        self.TT_CONFIG = MMIO(axi_base_addr + (axi_offset * axi_range),
                              axi_range)
        self.TT_CONFIG.write(ch2_data, 0x0)
        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
        self.IDELAY_DEBUG = MMIO(axi_base_addr + (axi_offset * axi_range),
                                 axi_range)
        plog.info("IDELAY_DEBUG: " + hex(axi_base_addr +
                                         (axi_offset * axi_range)))
        axi_offset += 1
        plog.debug("AXI_RANGE -- " + hex(axi_range))
        #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
        self.pg_ch_stat = 0xF
        sleep(0.05)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #self.PG_UTIL.write(ch2_data,0x0)
        sleep(0.1)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #Initial delay valus
        self.DDs = []
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
Exemplo n.º 7
0
import numpy as np
from PIL import Image
from time import time
import matplotlib.pyplot as plt

sys.path.append('/home/xilinx')
from pynq import Overlay
from pynq import allocate

if __name__ == "__main__":
    print("Entry:", sys.argv[0])
    print("System argument(s):", len(sys.argv))

    print("Start of \"" + sys.argv[0] + "\"")

    ol = Overlay("/home/xilinx/f04525034/histogram/design_1.bit")
    ipHist = ol.top_img_hist_equaliz1_0

    im = Image.open("/home/xilinx/f04525034/histogram/test_1080p.bmp")
    img = np.array(im).astype(np.uint8)

    #Buf = np.zeros(1080,dtype=np.int32)
    #for i in range(3):
    #    print(i*8)
    #    print(img[:,0,i]<<(i*8))
    #    Buf += img[:,0,i]<<(i*8)
    #print(Buf[0])

    test = img.transpose(1, 0, 2).reshape((-1, 3))
    print(img.shape)
    plt.title("Original colored image")
Exemplo n.º 8
0
#  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.
#
###############################################################################

print("Running testXfphase.py ...")
print("Loading overlay")
from pynq import Overlay
bs = Overlay("/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2phase.bit")
bs.download()

print("Loading xlnk")
from pynq import Xlnk
Xlnk.set_allocator_library('/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2phase.so')
mem_manager = Xlnk()

import pynq_cv.overlays.xv2phase as xv2
import numpy as np
import cv2
import time

import OpenCVUtils as cvu

print("Loading image ../images/bigBunny_1080.png")
Exemplo n.º 9
0
#!/usr/bin/env python
# coding: utf-8

# # Canny Edge
# 


from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from pynq import Xlnk, Overlay


canny = Overlay("canny.xclbin")

image_path = "input_image.jpg"
original_image = Image.open(image_path)

canny_edge = canny.canny_1
canny_edge.signature

low_threshold = 0
high_threshold = 255
height = 1920
width = 1080

in_buffer = allocate((height, width), np.uint8)
out_buffer = allocate((height, width), np.uint8)

start_time = time.time()
Exemplo n.º 10
0
#  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.
#
###############################################################################

print("Running testXfAccumulateWeighted.py ...")
print("Loading overlay")
from pynq import Overlay
bs = Overlay(
    "/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2accumulateWeighted.bit"
)
bs.download()

print("Loading xlnk")
from pynq import Xlnk
Xlnk.set_allocator_library(
    '/usr/local/lib/python3.6/dist-packages/pynq_cv/overlays/xv2accumulateWeighted.so'
)
mem_manager = Xlnk()

import pynq_cv.overlays.xv2accumulateWeighted as xv2
import numpy as np
import cv2
import time
Exemplo n.º 11
0
#Testing Sending data captured from the PS on the ZYNQ chip Temperature
#Collecting seven samples, sending the data to a custom IP on the PL to average the seven values
#Then send the result of the calculation back to the PS for printing
#John Tracey DCU August 2019 MECE
 
from pynq import Overlay
overlay = Overlay('/home/xilinx/pynq/overlays/average/average.bit')

test_funct = overlay.average_0

import time
temp= [None] * 7 # temp array for 7 values
count = 0
while count < 7: # getting the cpu temp 7 times
    count = count +1
    with open('/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_raw') as f: #open file to get cpu temp value
        for line in f:
            temp[count-1] = int(line) # populate the array with 7 sperate cpu temperature values
            print(temp[count-1])
            time.sleep(.005)
            
#write temperaturevalues to address 0x00 to 0x18 the values to registers a,b,c,d,e,f,g in programmable logic
test_funct.write(0x00, temp[0])
test_funct.write(0x04, temp[1])
test_funct.write(0x08, temp[2])
test_funct.write(0x0C, temp[3])
test_funct.write(0x10, temp[4])
test_funct.write(0x14, temp[5])
test_funct.write(0x18, temp[6])

#read from register h address 0x1C which should give the average of the 7 numbers sent to the IP
Exemplo n.º 12
0
    def __init__(self, addr_port_client=("192.168.1.100", 3000)):
        print('FPGA_Connect_Object init')
        self.resolution = [640, 360]
        self.client_port = addr_port_client

        team_name = 'SystemsETHZ'
        # agent = Agent(team_name)

        interval_time = 0
        xlnk = Xlnk()
        xlnk.xlnk_reset()

        ###########################variable initializing######################
        OVERLAY_PATH = '/home/xilinx/jupyter_notebooks/dac_2019_contest/common/' + team_name + '/ultra96_v04.bit'
        WEIGHTS_FILE_NAME = '/home/xilinx/jupyter_notebooks/dac_2019_contest/common/' + team_name + '/weights_file_v04_demo.txt'

        ###########################change board settings######################

        ###########################download      overlay######################
        overlay = Overlay(OVERLAY_PATH)
        self.dma = overlay.axi_dma_0
        self.nn_ctrl = MMIO(0xA0010000, length=1024)
        ###########################download      weights######################
        self.MINIBATCH_SIZE = 1
        self.height = 176
        self.width = 320
        pixel_bits = 24
        pixels_per_line = 384 / pixel_bits
        self.num_lines = int((self.height * self.width) / pixels_per_line)

        self.in_buffer = xlnk.cma_array(shape=(self.MINIBATCH_SIZE *
                                               self.num_lines, 64),
                                        dtype=np.uint8)
        fire1_num_out_lines = (self.height / 4) * (self.width /
                                                   4) * self.MINIBATCH_SIZE
        self.fire1_out_buffer = xlnk.cma_array(shape=(int(
            16 * fire1_num_out_lines), ),
                                               dtype=np.uint32)
        fire2_num_out_lines = (self.height / 8) * (self.width /
                                                   8) * self.MINIBATCH_SIZE
        self.fire2_out_buffer = xlnk.cma_array(shape=(int(
            16 * fire2_num_out_lines), ),
                                               dtype=np.uint32)
        fire3_num_out_lines = (self.height / 16) * (self.width /
                                                    16) * self.MINIBATCH_SIZE
        self.fire3_out_buffer = xlnk.cma_array(shape=(int(
            16 * fire3_num_out_lines), ),
                                               dtype=np.uint32)
        self.fire4_out_buffer = xlnk.cma_array(shape=(int(
            16 * fire3_num_out_lines), ),
                                               dtype=np.uint32)
        self.fire5_out_buffer = xlnk.cma_array(shape=(int(
            16 * fire3_num_out_lines), ),
                                               dtype=np.uint32)
        final_num_lines = int((self.height / 16) * (self.width / 16))
        self.bndboxes = [
            xlnk.cma_array(shape=(self.MINIBATCH_SIZE, final_num_lines, 16),
                           dtype=np.int32),
            xlnk.cma_array(shape=(self.MINIBATCH_SIZE, final_num_lines, 16),
                           dtype=np.int32),
            xlnk.cma_array(shape=(self.MINIBATCH_SIZE, final_num_lines, 16),
                           dtype=np.int32),
            xlnk.cma_array(shape=(self.MINIBATCH_SIZE, final_num_lines, 16),
                           dtype=np.int32)
        ]
        self.obj_array = np.zeros((self.MINIBATCH_SIZE, final_num_lines))

        NUM_LAYERS = 3 + 4 * 4
        weights_file = open(WEIGHTS_FILE_NAME, "r")
        layer = 0
        total_iterations = np.zeros(NUM_LAYERS)
        for line in weights_file:
            if "layer" in line:
                temp = line.split(": ")
                layer = int(temp[1])
            if "total_iterations" in line:
                temp = line.split(": ")
                total_iterations[layer] = int(temp[1])
        weights_file.close()

        weightfactors_length = np.zeros(NUM_LAYERS)
        self.weightsfactors = []
        for i in range(0, NUM_LAYERS):
            weightfactors_length[i] = int(total_iterations[i])
            self.weightsfactors.append(
                xlnk.cma_array(shape=(int(16 * weightfactors_length[i]), ),
                               dtype=np.uint32))
        self.obj_factors = np.zeros(4)
        self.box_factors = np.zeros(4)

        index = 0
        weights_file = open(WEIGHTS_FILE_NAME, "r")
        for line in weights_file:
            if "layer" in line:
                temp = line.split(": ")
                layer = int(temp[1])
                index = 0
            elif "total_iterations" not in line:
                if "obj_factor" in line:
                    temp = line.split(' ')
                    self.obj_factors[int(temp[1])] = int(temp[2])
                elif "box_factor" in line:
                    temp = line.split(' ')
                    self.box_factors[int(temp[1])] = int(temp[2])
                else:
                    no0x = line.split('0x')[-1]
                    base = 1
                    while base < len(no0x):
                        part = no0x[-1 * (base + 8):-1 * base]
                        self.weightsfactors[layer][index * 16 +
                                                   int(base / 8)] = int(
                                                       part, 16)
                        base += 8
                    index += 1
Exemplo n.º 13
0
from pynq import Overlay
import sys
import socket

ol = Overlay('design_1.bit')
ol.download()

print('Loaded bitstream')

# Load the two AXI devices into variables
buf = ol.axi_bram_ctrl_0
nic = ol.Pmod_NIC100_AXI_0

# Some offsets for the AXI nic
busy = 0
rx_tx = 4
rx_len = 8
tx_len = 12

# Constants
BITMASK_RX = 0b01
BITMASK_TX = 0b10
ARP_REQUEST = [0, 1]
ETH_TYPE_ARP = [0x08, 0x06]
ETH_TYPE_IP = [0x08, 0x00]
ICMP_PING_REPLY = [0x00]
ICMP_PING_REQUEST = [0x08]
IP_BASE = [192, 168, 2, 99]
IP_PROT_ICMP = [0x01]
MAC_BASE = [0xab] * 6
MAC_BROADCAST = [0xff] * 6
Exemplo n.º 14
0
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)
            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)
                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)
            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)
                while not self.dmaOut.idle and not self.dmaOut._first_transfer:
                    pass 
                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 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
    def __init__(self):
        global dma

        self.dance_labels = np.array(['dab', 'elbowkick', 'gun', 'hair', 'left', 'listen', 'pointhigh', 'right', 'sidepump', 'logout', 'stationary', 'wipetable'])
        self.pos_labels = np.array(['left', 'right', 'stationary'])

        dance_weights_dir = "weights_dance_sat_40_mav_10_new"
        pos_weights_dir = "weights_pos_sat_40_mav_10_stat"

        weight_0 = np.load(f'{dance_weights_dir}/weight_0.npy')
        weight_1 = np.load(f'{dance_weights_dir}/weight_1.npy')
        weight_2 = np.load(f'{dance_weights_dir}/weight_2.npy')
        weight_3 = np.load(f'{dance_weights_dir}/weight_3.npy')
        weight_4 = np.load(f'{dance_weights_dir}/weight_4.npy')
        bias_0 = np.load(f'{dance_weights_dir}/bias_0.npy')
        bias_1 = np.load(f'{dance_weights_dir}/bias_1.npy')
        bias_2 = np.load(f'{dance_weights_dir}/bias_2.npy')
        bias_3 = np.load(f'{dance_weights_dir}/bias_3.npy')
        bias_4 = np.load(f'{dance_weights_dir}/bias_4.npy')
        weight_0_pos = np.load(f'{pos_weights_dir}/weight_0.npy')
        weight_1_pos = np.load(f'{pos_weights_dir}/weight_1.npy')
        weight_2_pos = np.load(f'{pos_weights_dir}/weight_2.npy')
        weight_3_pos = np.load(f'{pos_weights_dir}/weight_3.npy')
        bias_0_pos = np.load(f'{pos_weights_dir}/bias_0.npy')
        bias_1_pos = np.load(f'{pos_weights_dir}/bias_1.npy')
        bias_2_pos = np.load(f'{pos_weights_dir}/bias_2.npy')
        bias_3_pos = np.load(f'{pos_weights_dir}/bias_3.npy')
        self.scaler_mean = np.load(f'{dance_weights_dir}/mean.npy')
        self.scaler_scale = np.load(f'{dance_weights_dir}/scale.npy')
        self.scaler_mean_pos = np.load(f'{pos_weights_dir}/scaler_mean.npy')
        self.scaler_scale_pos = np.load(f'{pos_weights_dir}/scaler_scale.npy')

        overlay = Overlay('final.bit')   # load bitstream inside FPGA
        dma = overlay.axi_dma_0    

        self.choose_model = allocate(shape=(1,), dtype=np.float32)
        input_buffer0 = allocate(shape=(100,), dtype=np.float32)
        input_buffer1 = allocate(shape=(128,), dtype=np.float32)
        input_buffer2 = allocate(shape=(12,), dtype=np.float32)
        input_buffer3 = allocate(shape=(32,), dtype=np.float32)
        input_buffer4 = allocate(shape=(3,), dtype=np.float32)
        output_buffer0 = allocate(shape=(12,), dtype=np.float32)
        output_buffer1 = allocate(shape=(3,), dtype=np.float32)

        ##load dance weights
        for i in range(128):
            for k in range(100):
                input_buffer0[k] = weight_0[k][i]
            dma.sendchannel.transfer(input_buffer0)
            dma.sendchannel.wait()
        for i in range(128):
            for k in range(128):
                input_buffer1[k] = weight_1[k][i]
            dma.sendchannel.transfer(input_buffer1)
            dma.sendchannel.wait()
        for i in range(128):
            for k in range(128):
                input_buffer1[k] = weight_2[k][i]
            dma.sendchannel.transfer(input_buffer1)
            dma.sendchannel.wait()
        for i in range(128):
            for k in range(128):
                input_buffer1[k] = weight_3[k][i]
            dma.sendchannel.transfer(input_buffer1)
            dma.sendchannel.wait()
        for i in range(12):
            for k in range(128):
                input_buffer1[k] = weight_4[k][i]
            dma.sendchannel.transfer(input_buffer1)
            dma.sendchannel.wait()
        ##bias
        for k in range(128):
            input_buffer1[k] = bias_0[k]
        dma.sendchannel.transfer(input_buffer1)
        dma.sendchannel.wait()
        for k in range(128):
            input_buffer1[k] = bias_1[k]
        dma.sendchannel.transfer(input_buffer1)
        dma.sendchannel.wait()
        for k in range(128):
            input_buffer1[k] = bias_2[k]
        dma.sendchannel.transfer(input_buffer1)
        dma.sendchannel.wait()
        for k in range(128):
            input_buffer1[k] = bias_3[k]
        dma.sendchannel.transfer(input_buffer1)
        dma.sendchannel.wait()
        for k in range(12):
            input_buffer2[k] = bias_4[k]
        dma.sendchannel.transfer(input_buffer2)
        dma.sendchannel.wait()
    
        ##load position weights
        for i in range(32):
            for k in range(100):
                input_buffer0[k] = weight_0_pos[k][i]
            dma.sendchannel.transfer(input_buffer0)
            dma.sendchannel.wait()
        for i in range(32):
            for k in range(32):
                input_buffer3[k] = weight_1_pos[k][i]
            dma.sendchannel.transfer(input_buffer3)
            dma.sendchannel.wait()
        for i in range(32):
            for k in range(32):
                input_buffer3[k] = weight_2_pos[k][i]
            dma.sendchannel.transfer(input_buffer3)
            dma.sendchannel.wait()
        for i in range(3):
            for k in range(32):
                input_buffer3[k] = weight_3_pos[k][i]
            dma.sendchannel.transfer(input_buffer3)
            dma.sendchannel.wait()
        ##bias
        for k in range(32):
            input_buffer3[k] = bias_0_pos[k]
        dma.sendchannel.transfer(input_buffer3)
        dma.sendchannel.wait()
        for k in range(32):
            input_buffer3[k] = bias_1_pos[k]
        dma.sendchannel.transfer(input_buffer3)
        dma.sendchannel.wait()
        for k in range(32):
            input_buffer3[k] = bias_2_pos[k]
        dma.sendchannel.transfer(input_buffer3)
        dma.sendchannel.wait()
        for k in range(3):
            input_buffer4[k] = bias_3_pos[k]
        dma.sendchannel.transfer(input_buffer4)
        dma.sendchannel.wait()

        self.fns = [getattr(features,f) for f in features.__dict__ if callable(getattr(features, f)) and f.startswith("get_")]
Exemplo n.º 16
0
from pynq import Overlay
from pynq import Xlnk
import numpy as np
import cv2
from PIL import Image as PIL_Image
from PIL import ImageEnhance
from PIL import ImageOps
from scipy import misc

overlay = Overlay('lenet.bit')
top = overlay.top_fun_0


# 寄存器地址
# CTRL           0x00
# IN_DRAM_DATA      0x10
# W_DRAM_DATA       0x18
# OUT_DRAM_DATA      0x20
# BIAS_DRAM_DATA     0x28
# LAYER_DATA        0x30
def top_fun(pic_in, w_in, out, bias, layer):
    top.write(0x10, pic_in)  #pic_in
    top.write(0x18, w_in)  #w
    top.write(0x20, out)  #out
    top.write(0x28, bias)  #bias
    top.write(0x30, layer)  #layer
    top.write(0x00, 0x01)  #写入1 将ap_start置1 启动
    while (top.read(0) != 0x04):  #等待完成
        a = 1
    return 0
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 24 11:44:12 2019

@author: LHN
"""
import time
start = time.clock()

import numpy
import os

from pynq import Overlay
overlay=Overlay('/home/xilinx/pynq/overlays/distance/diatance.bit')
overlay?
distance_ip=overlay.distance
distance_ip?
#定义一个三维点类
class Point(object):
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z
points = []
filename = '/home/workspace/horse_1100.pcd'
filename2 = '/home/workspace/horse_1100_dataRadiusOutlierRemoval'
#读取pcd文件,从pcd的第12行开始是三维点

with open(filename+'.pcd') as f:
    for line in  f.readlines()[11:len(f.readlines())-1]:
        strs = line.split(' ')
Exemplo n.º 18
0
                        scalar_args.append(ba.arguments[param.name])
                return Call(vlnv,
                            stream_args,
                            scalar_args,
                            return_type=ret_type)
            else:
                return func(*args, **kwargs)

        return wrapped_function

    return decorator


from pynq import Overlay

Overlay('base.bit').download()
from pynq.drivers import DMA
import pynq.drivers.dma

Overlay(
    '/home/xilinx/jupyter_notebooks/PYNQ_CNN/Theano/Lenet/Bitstream/lenet.bit'
).download()


def prepare_execution(plan, dma, return_port):
    if type(plan) is Wrapper:
        d = DMAWrapper(len(dma))
        d.set_data(plan.wrapped, plan.dtype())
        dma.append(d)
        hw_switch.set_route(d.ports[1][0], return_port)
    elif type(plan) is Call:
Exemplo n.º 19
0
img   = xlnk.cma_array(shape=[160,320,16], dtype=np.uint8)
fm    = xlnk.cma_array(shape=(628115*32), dtype=np.uint8)
weight = xlnk.cma_array(shape=(220672),  dtype=np.int16)
biasm  = xlnk.cma_array(shape=(432*16),  dtype=np.int16)
bbox = np.empty(64, dtype=np.int16)
print("Allocating memory done")

parameter = np.fromfile("SkyNet.bin", dtype=np.int16)

np.copyto(weight, parameter[0:220672])
np.copyto(biasm[0:428*16], parameter[220672:])
print("Parameters loading done")


overlay = Overlay("SEUer2.bit")
print("Bitstream loaded")

SkyNet = overlay.SkyNet_0
SkyNet.write(0x10, img.physical_address)
SkyNet.write(0x1c, fm.physical_address)
SkyNet.write(0x28, weight.physical_address)
SkyNet.write(0x34, biasm.physical_address)

rails = pynq.get_rails()
recorder = pynq.DataRecorder(rails['5V'].power)

IMAGE_NAMES   = get_image_batch()
IMAGE_NAMES_LEN = len(IMAGE_NAMES)

image_queue = Queue(1000)
Exemplo n.º 20
0
	#os.write(temp, bytes("5 10\n", "utf-8")); 
	#os.close(temp)
	print(location)
	# store output of the program as a byte string in s 
	# s = subprocess.check_output("../octomap/octomap/bin/shared_mem_to_bt "+location, stdin = data, shell = True) 
	# stream = os.popen("../octomap/octomap/bin/shared_mem_to_bt "+location)
	# output = stream.read()
	# print(output)
	os.system("../octomap/octomap/bin/shared_mem_to_bt "+location)
	# decode s to a normal string 
	#print(s.decode("utf-8")) 
	#print(s)

if __name__ == "__main__":
	#overlay = Overlay('/home/xilinx/sgm_pynq_ver/census_mgm_multi_bit/design_1.bit')
	overlay = Overlay('./Bitstream/5Sections/design_1.bit')
	overlay
	ffi = cffi.FFI() #Being used to convert FPGA accessable memory to np array
	capl = cv2.VideoCapture(0)

	#image = cv2.imread('/home/xilinx/sgm_pynq_ver/test_images/right_image32.jpg', 0);
	imagel = np.zeros((ZED_IMAGE_HEIGHT,ZED_IMAGE_WIDTH),dtype=np.ubyte)
	imager = np.zeros((ZED_IMAGE_HEIGHT,ZED_IMAGE_WIDTH),dtype=np.ubyte)
	rectified_left = np.zeros((ZED_IMAGE_HEIGHT,ZED_IMAGE_WIDTH),dtype=np.ubyte)
	rectified_right = np.zeros((ZED_IMAGE_HEIGHT,ZED_IMAGE_WIDTH),dtype=np.ubyte)
	buffer_left = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte)
	buffer_right = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte)
	disp_median_buff = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte)

	# imagel[0:ZED_IMAGE_HEIGHT,0:640] = image[0:ZED_IMAGE_HEIGHT,0:640]
	# imager[0:ZED_IMAGE_HEIGHT,0:640] = image[0:ZED_IMAGE_HEIGHT,672:1312]
Exemplo n.º 21
0
def gradients_kernel_accel(data, weights):
    numClasses = 10
    numFeatures = 784
    chunkSize = int(len(data) / (numClasses + (1 + 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.
    # -------------------------

    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.
    # -------------------------

    dma0 = DMA(ADDR_DMA0_BASE, direction=DMA_TO_DEV)  # data1 DMA
    dma1 = DMA(ADDR_DMA1_BASE, direction=DMA_TO_DEV)  # data2 DMA
    dma2 = DMA(ADDR_DMA2_BASE, direction=DMA_TO_DEV)  # weights DMA
    dma3 = DMA(ADDR_DMA3_BASE, direction=DMA_FROM_DEV)  # gradients DMA

    # -------------------------
    #    Allocate physically contiguous memory buffers.
    # -------------------------

    dma0.create_buf(int(chunkSize * (numClasses + (1 + numFeatures)) / 2) * 4)
    dma1.create_buf(int(chunkSize * (numClasses + (1 + numFeatures)) / 2) * 4)
    dma2.create_buf((numClasses * (1 + numFeatures)) * 4)
    dma3.create_buf((numClasses * (1 + numFeatures)) * 4)

    # -------------------------
    #    Get CFFI pointers to objects' internal buffers.
    # -------------------------

    data1_buf = dma0.get_buf(data_type="float")
    data2_buf = dma1.get_buf(data_type="float")
    weights_buf = dma2.get_buf(data_type="float")
    gradients_buf = dma3.get_buf(data_type="float")

    for i in range(0, int(chunkSize * (numClasses + (1 + numFeatures)) / 2)):
        data1_buf[i] = float(data[i])
        data2_buf[i] = float(
            data[int(chunkSize * (numClasses + (1 + numFeatures)) / 2) + i])
    for kj in range(0, numClasses * (1 + numFeatures)):
        weights_buf[kj] = float(weights[kj])

    # -------------------------
    #   Write data to MMIO.
    # -------------------------

    CMD = 0x0028  # Command.
    ISCALAR0_DATA = 0x0080  # Input Scalar-0 Write Data FIFO.

    bus.write(ISCALAR0_DATA, int(chunkSize))
    bus.write(CMD, 0x00010001)
    bus.write(CMD, 0x00020000)
    bus.write(CMD, 0x00000107)

    # -------------------------
    #   Transfer data using DMAs (Non-blocking).
    #   Block while DMAs are busy.
    # -------------------------

    dma0.transfer(int(chunkSize * (numClasses + (1 + numFeatures)) / 2) * 4,
                  direction=DMA_TO_DEV)
    dma1.transfer(int(chunkSize * (numClasses + (1 + numFeatures)) / 2) * 4,
                  direction=DMA_TO_DEV)
    dma2.transfer((numClasses * (1 + numFeatures)) * 4, direction=DMA_TO_DEV)

    dma0.wait()
    dma1.wait()
    dma2.wait()

    dma3.transfer((numClasses * (1 + numFeatures)) * 4, direction=DMA_FROM_DEV)

    dma3.wait()

    gradients = []
    for kj in range(0, numClasses * (1 + numFeatures)):
        gradients.append(float(gradients_buf[kj]))

    # -------------------------
    #   Destructors for DMA objects.
    # -------------------------

    dma0.__del__()
    dma1.__del__()
    dma2.__del__()
    dma3.__del__()

    return gradients
Exemplo n.º 22
0
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("SP_OVERLAY.bit", 0)
        self.OV.download()
        axi_offset = 0
        ##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
        #43c4
        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
        #43c8
        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)))
        axi_offset += 1
        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)
        #43c9
        ##Initialize IDELAY
        self.DELAY_TAPS = MMIO(axi_base_addr + (axi_offset * axi_range),
                               0x10000)

        plog.info("IDELAY: " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43ca

        ##Initialize pulse counter
        #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("PCDAT" + str(i) + " -- " +
                      hex(axi_base_addr + (axi_offset * axi_range)))
            axi_offset += 1
        #43ce
        #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("PCUT" + str(i) + " -- " + hex(axi_base_addr +
                                                     (axi_offset * axi_range)))
            axi_offset += 1
        #43d2
        #Initialize trigger controller
        self.T_UTIL = MMIO(0x41210000, 0x10000)
        self.T_UTIL.write(ch2_dir, 0x0)
        self.T_UTIL.write(ch2_data, 0x0)
        self.T_RDY_UTIL = MMIO(0x41200000, 0x10000)
        self.T_RDY_UTIL.write(ch1_dir, 0x1)
        ##Initialize single channel inter-rising_edge detection
        self.ST_FIFO_BUFFER = []
        self.ST_loaded_count = 0
        for i in range(FIFO_DEPTH):
            self.ST_FIFO_BUFFER.append(0)
        self.ST_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range)
        plog.info("STDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.ST_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.ST_UTIL.write(ch1_data, 0x0)
        plog.info("STUTIL -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        ##Initialize interchannel coincidence timer
        self.CT_FIFO_BUFFER = []
        self.CT_loaded_count = 0
        for i in range(FIFO_DEPTH):
            self.CT_FIFO_BUFFER.append(0)
        self.CT_DATA = MMIO(axi_base_addr + axi_offset * axi_range, axi_range)
        plog.info("CTDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.CT_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.CT_UTIL.write(ch1_data, self.CT_UTIL.read(0x0) & 0b110)
        plog.info("CTUTIL -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43d6
        ##Initialize time tagger
        self.TT_FIFO_BUFFER = []
        for i in range(FIFO_DEPTH):
            self.TT_FIFO_BUFFER.append(0)
        self.TT_loaded_count = 0
        self.TT_CONFIG = MMIO(axi_base_addr + (axi_offset * axi_range),
                              axi_range)
        self.TT_CONFIG.write(ch2_data, 0x0)
        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
        self.IDELAY_DEBUG = MMIO(axi_base_addr + (axi_offset * axi_range),
                                 axi_range)
        plog.info("IDELAY_DEBUG: " + hex(axi_base_addr +
                                         (axi_offset * axi_range)))
        axi_offset += 1
        plog.debug("AXI_RANGE -- " + hex(axi_range))
        #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
        self.pg_ch_stat = 0xF
        sleep(0.05)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #self.PG_UTIL.write(ch2_data,0x0)
        sleep(0.1)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #Initial delay valus
        self.DDs = []
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)

    def restart(self):
        self.__init__()

    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_read_coarse(self):
        """
        Reads coarse timer counter value
        Returns
        -------
        :class:`int`
            Interdetection time in counter clock cycles
        """
        return self.ST_DATA.read(0x0)

    def st_read_fine(self):
        """
        Reads the fine time offsets from the rising edge of the coarse clock.
        Returns
        -------
        :class:`int` Fine time offsets
        """
        return self.ST_DATA.read(0x8)

    def st_read_drdy(self):
        """
        Reads whether data is valid to be read
        Returns
        -------
        :class:`int`
            Value of the valid line (0 or 1)
        """
        return self.ST_UTIL.read(0x8) & 0b1

    def st_read_empty(self):
        """
        Reads whether the FIFO is empty
        Returns
        -------
        :class:`int`
            0 or 1 for not empty and empty respectively
        """
        return (self.ST_UTIL.read(0x8) & 0b10) >> 1

    def st_read_full(self):
        """
        Reads whether the FIFO is full
        Returns
        -------
        :class:`int`
            0 or 1 for not full and full respectively
        """
        return (self.ST_UTIL.read(0x8) & 0b100) >> 1

    def st_set_mreset(self, val):
        """
        Sets the master reset of the module (active low), when in reset the module is disabled
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.ST_UTIL.read(0x0) & 0b110
        self.ST_UTIL.write(0x0, lastval | (val & 0b1))

    def st_set_req(self, val):
        """
        Sets the data request line to indicate to the FIFO read controller to clock a single data point out of the FIFO (ACTIVE HIGH)
        Parameters
        ----------
        val : :class:`int`
            Value of the request line (0 or 1)

        """
        lastval = self.ST_UTIL.read(0x0) & 0b101
        self.ST_UTIL.write(0x0, lastval | ((val << 1) & 0b10))

    def st_set_dreset(self, val):
        """
        SEts the FIFO read controller's reset, to reset it back to awaiting a request signal (active low)
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.ST_UTIL.read(0x0) & 0b011
        self.ST_UTIL.write(0x0, lastval | ((val << 2) & 0b100))

    def st_start(self):
        """
        Starts the single channel inter rising edge timer module

        """
        self.st_set_mreset(1)

    def st_stop(self):
        """
        Stops the inter rising edge timer module

        """
        self.st_set_mreset(0)
        self.st_set_dreset(0)

    def st_flush_buffer(self):
        """
        HELPER - NOT USED CURRENTLY - Flushes the local FIFO buffer (NOT THE HARDWARE FIFO, TO Do THAT CAL st_read2048() AND THEN FLUSH)

        """
        for i in range(FIFO_DEPTH):
            self.ST_FIFO_BUFFER[i] = 0
        self.ST_loaded_count = 0

    def st_proc(self):
        """
        Reads 2048 values from the FIFO (or until empty) and places the data into a dictionary with length and module ID ready to be sent over socket.
        Returns
        -------
        :class:`dict`
            Dictionary containing module identification, length of data list, and the data list
        """
        self.st_read2048()
        return {
            "MOD": "ST",
            "LEN": self.ST_loaded_count,
            "DAT": self.ST_FIFO_BUFFER
        }

    def st_read2048(self):
        """
        Reads data from the FIFO until empty and stores each recovered data point in the local FIFO buffer.

        """
        if (self.st_read_empty() == 1):
            plog.warning("FIFO EMPTY")
            return
        for i in range(FIFO_DEPTH):
            if (self.st_read_empty() == 1):
                self.ST_loaded_count = i
                return
            self.st_set_dreset(
                1)  #Pull FIFO read controller out of reset and request data
            self.st_set_req(1)
            while (self.st_read_drdy() == 0):
                pass
            self.ST_FIFO_BUFFER[i] = self.st_read_coarse() | self.st_read_fine(
            ) << 32  #Concatenate both fine and coarse times and store the resulting value into the local buffer
            #print(self.loaded_data[i]&0xFFFFFFFF)
            self.st_set_req(
                0)  #Deassert the request line and reset the read controller
            self.st_set_dreset(0)
        self.ST_loaded_count = FIFO_DEPTH

    ####----------------------------------------------------------------------------------####
    ####------------------Two channel photon coincidence timer----------------------------####
    def ct_start(self, mode):
        """
        Starts the two channel coincidence timer
        Parameters
        ----------
        mode : :class:`int`
            Line select mode, whether to treat the first channel as start or second, or whichever is detected first (0,1,2)

        """
        if (mode != 2):
            self.ct_set_fsel(mode)
            self.ct_set_bidir(0)
        else:
            self.ct_set_bidir(1)
        self.ct_set_mreset(1)

    def ct_stop(self):
        """
        Stops the two channel coincidence timer

        """
        self.ct_set_mreset(0)

    def ct_flush_buffer(self):
        """
        HELPER - NOT USED CURRENTLY - Flushes the local FIFO buffer (NOT THE HARDWARE FIFO, TO Do THAT CAL ct_read2048() AND THEN FLUSH)

        """
        for i in range(FIFO_DEPTH):
            self.CT_FIFO_BUFFER[i] = 0
        self.loaded_count = 0

    def ct_proc(self):
        """
        Reads 2048 values from the FIFO (or until empty) and places the data into a dictionary with length and module ID ready to be sent over socket.
        Returns
        -------
        :class:`dict`
            Dictionary containing module identification, length of data list, and the data list

        """
        self.ct_read2048()
        return {
            "MOD": "CT",
            "LEN": self.loaded_count,
            "DAT": self.CT_FIFO_BUFFER
        }

    def ct_read2048(self):
        """
        Reads data from the FIFO until empty and stores each recovered data point in the local FIFO buffer.

        """
        if (self.ct_read_empty() == 1):
            return
        for i in range(FIFO_DEPTH):
            if (self.ct_read_empty() == 1):
                self.loaded_count = i
                return
            self.ct_set_dreset(1)
            self.ct_set_req(1)
            while (self.ct_read_drdy() == 0):
                pass
            self.CT_FIFO_BUFFER[i] = self.ct_read_coarse(
            ) | self.ct_read_fine() << 32
            #print(self.loaded_data[i]&0xFFFFFFFF)
            self.ct_set_req(0)
            self.ct_set_dreset(0)
        self.loaded_count = FIFO_DEPTH

    def ct_read_coarse(self):
        """
        Reads coarse timer counter value
        Returns
        -------
        :class:`int`
            Interdetection time in counter clock cycles
        """
        return self.CT_DATA.read(0x0)

    def ct_read_fine(self):
        """
        Reads the fine time offsets from the rising edge of the coarse clock.
        Returns
        -------
        :class:`int` Fine time offsets
        """
        return self.CT_DATA.read(0x8)

    def ct_set_fsel(self, val):
        """
        Sets the first detection channel select line.
        Parameters
        ----------
        val : :class:`int`
            0 to treat Ch1 as start signal, 1 to treat CH2 as start signal

        """
        lastval = self.CT_UTIL.read(0x0) & 0b11101
        self.CT_UTIL.write(0x0, lastval | ((val << 1) & 0b10))

    def ct_set_bidir(self, val):
        """
        Sets whether the module chooses the start signal based on which channel is detected first (ACTIVE HIGH), if set, the setting of ct_set_fsel() is ignored.
        Parameters
        ----------
        val : :class:`int`
            0 or 1 to give precendence to fsel line or to pick based off which comes first respectively.

        Returns
        -------

        """
        lastval = self.CT_UTIL.read(0x0) & 0b11011
        self.CT_UTIL.write(0x0, lastval | ((val << 2) & 0b100))

    def ct_read_drdy(self):
        """
        Reads whether data is valid to be read
        Returns
        -------
        :class:`int`
            Value of the valid line (0 or 1)
        """
        return self.CT_UTIL.read(0x8) & 0b1

    def ct_read_empty(self):
        """
        Reads whether the FIFO is empty
        Returns
        -------
        :class:`int`
            0 or 1 for not empty and empty respectively
        """
        return (self.CT_UTIL.read(0x8) & 0b10) >> 1

    def ct_read_full(self):
        """
        Reads whether the FIFO is full
        Returns
        -------
        :class:`int`
            0 or 1 for not full and full respectively
        """
        return (self.CT_UTIL.read(0x8) & 0b100) >> 1

    def ct_set_mreset(self, val):
        """
        Sets the master reset of the module (active low), when in reset the module is disabled
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.CT_UTIL.read(0x0) & 0b11110
        self.CT_UTIL.write(0x0, lastval | (val & 0b1))

    def ct_set_req(self, val):
        """
        Sets the data request line to indicate to the FIFO read controller to clock a single data point out of the FIFO (ACTIVE HIGH)
        Parameters
        ----------
        val : :class:`int`
            Value of the request line (0 or 1)

        """
        lastval = self.CT_UTIL.read(0x0) & 0b01111
        self.CT_UTIL.write(0x0, lastval | ((val << 4) & 0b10000))

    def ct_set_dreset(self, val):
        """
        SEts the FIFO read controller's reset, to reset it back to awaiting a request signal (active low)
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.CT_UTIL.read(0x0) & 0b10111
        self.CT_UTIL.write(0x0, lastval | ((val << 3) & 0b1000))

    ####---------------------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 = DDS_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) / DDS_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(DDS_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 * DDS_REF_CLK)

    #TIME TAGGER FUNCTIONS-----------------------------------------------
    def tt_start(self, timeout):
        """
        Starts the time tagger module
        Parameters
        ----------
        timeout : :class:`int`
            Number of counter cycles to wait for.

        """
        self.tt_set_timeout(timeout)
        self.tt_set_mreset(1)

    def tt_stop(self):
        """
        Stops the time tagger

        """
        self.tt_set_mreset(0)

    def tt_flush_buffer(self):
        """
        HELPER - NOT USED CURRENTLY - Flushes the local FIFO buffer (NOT THE HARDWARE FIFO, TO Do THAT CAL tt_read2048() AND THEN FLUSH)

        """
        for i in range(FIFO_DEPTH):
            self.TT_FIFO_BUFFER[i] = 0
        self.TT_loaded_count = 0

    def tt_proc(self):
        """
        Reads 2048 values from the FIFO (or until empty) and places the data into a dictionary with length and module ID ready to be sent over socket.
        Returns
        -------
        :class:`dict`
            Dictionary containing module identification, length of data list, and the data list

        """
        self.tt_read2048()
        data = {
            "MOD": "TT",
            "LEN": self.TT_loaded_count,
            "DAT": self.TT_FIFO_BUFFER
        }
        return data

    def tt_read2048(self):
        """
        Reads data from the FIFO until empty and stores each recovered data point in the local FIFO buffer.

        """
        if (self.tt_read_empty() == 1):
            return
        for i in range(FIFO_DEPTH):
            if (self.tt_read_empty() == 1):
                self.TT_loaded_count = i
                return
            self.tt_set_dreset(1)
            self.tt_set_req(1)
            while (self.tt_read_drdy() == 0):
                pass
            #Concatenate each part of current run (Coarse and fine times for each channel and time outs) into a singular integer and place in local buffer
            self.TT_FIFO_BUFFER[i] = ((self.tt_read_coarse()
                                       | self.tt_read_fine() << 128
                                       | self.tt_read_timeouts() << 168))
            self.tt_set_req(0)
            self.tt_set_dreset(0)
        self.TT_loaded_count = FIFO_DEPTH

    def tt_read_coarse(self):
        """
        Reads coarse timer counter value
        Returns
        -------
        :class:`int`
            Concatenated coarse times for each channel
        """
        d0 = self.TT_DATA0.read(0x0)
        d1 = self.TT_DATA0.read(0x8) << 32
        d2 = self.TT_DATA1.read(0x0) << 64
        d3 = self.TT_DATA1.read(0x8) << 96
        return d0 | d1 | d2 | d3

    def tt_read_fine(self):
        """
        Reads the fine time offsets from the rising edge of the coarse clock.
        Returns
        -------
        :class:`int`
        Concatenated fine time offsets for each channel.
        """
        return self.TT_DELAY_DATA.read(0x0) | (self.TT_DELAY_DATA.read(0x8)
                                               & 0xFF) << 32

    def tt_read_drdy(self):
        """
        Reads whether data is valid to be read
        Returns
        -------
        :class:`int`
            Value of the valid line (0 or 1)
        """
        return (self.TT_UTIL.read(0x8) & 0b100) >> 2

    def tt_read_empty(self):
        """
        Reads whether the FIFO is empty
        Returns
        -------
        :class:`int`
            0 or 1 for not empty and empty respectively
        """
        return (self.TT_UTIL.read(0x8) & 0b1)

    def tt_read_full(self):
        """
        Reads whether the FIFO is full
        Returns
        -------
        :class:`int`
            0 or 1 for not full and full respectively
        """
        return (self.TT_UTIL.read(0x8) & 0b10) >> 1

    def tt_set_mreset(self, val):
        """
        Sets the master reset of the module (active low), when in reset the module is disabled
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.TT_CONFIG.read(0x8) & 0b110
        self.TT_CONFIG.write(0x8, lastval | (val & 0b1))

    def tt_set_req(self, val):
        """
        Sets the data request line to indicate to the FIFO read controller to clock a single data point out of the FIFO (ACTIVE HIGH)
        Parameters
        ----------
        val : :class:`int`
            Value of the request line (0 or 1)

        """
        lastval = self.TT_CONFIG.read(0x8) & 0b101
        self.TT_CONFIG.write(0x8, lastval | ((val << 1) & 0b10))

    def tt_set_dreset(self, val):
        """
        SEts the FIFO read controller's reset, to reset it back to awaiting a request signal (active low)
        Parameters
        ----------
        val : :class:`int`
            Value of the reset line (0 or 1)

        """
        lastval = self.TT_CONFIG.read(0x8) & 0b011
        self.TT_CONFIG.write(0x8, lastval | ((val << 2) & 0b100))

    def tt_set_timeout(self, val):
        """
        Sets the time out data bus for the time tagger
        Parameters
        ----------
        val : :class:`int`
            32 bit integer stating the time out in TDC_REF_CLK cycles

        """
        self.TT_CONFIG.write(0x0, val & 0xFFFFFFFF)

    def tt_read_timeouts(self):
        """
        Reads the channel time out statuses
        Returns
        -------
        :class:`int`
            4 bit binary encoded integer showing the time out state for each line (0 if the channel timed out)
        """
        return self.TT_UTIL.read(0x0)

    #TIME_TAGGER_END-----------------------------------------------------

    def DD_idelay(self, channel, tap0, tap1):
        """Sets the input delay of the specified channel by configuring the delay line taps and the number of delay line stages to include
           Channels 4 and 5 are T0 and END TRIG
        Parameters
        ----------
        channel : :class:`int`
            Channel to delay (0-5)
        tap0 : :class:`int`
            Delay line tap (0-31)
         tap1 : :class:`int`
            Delay line cascaded tap (0-31)
        """

        concattaps = tap0 | (tap1 << 5)
        self.DDs[channel] = concattaps
        allconcat0 = self.DDs[4] | (self.DDs[0] << 10) | (self.DDs[1] << 20)
        allconcat1 = self.DDs[2] | (self.DDs[3] << 10) | (self.DDs[5] << 20)
        self.DELAY_TAPS.write(0x0, allconcat0)
        self.DELAY_TAPS.write(0x8, allconcat1)
        # if(channel <=2):
        #     dp0 = self.DELAY_TAPS.read(0x0) | (0b1111111111 << (channel*10))
        #     dp1 = dp0 & (concattaps << (channel*10))
        #     self.DELAY_TAPS.write(0x0,dp1)
        # else:
        #     dp0 = self.DELAY_TAPS.read(0x8) | (0b1111111111 << ((channel-3) * 10))
        #     dp1 = dp0 & (concattaps << ((channel-3) * 10))
        #     self.DELAY_TAPS.write(0x8, dp1)
        plog.info("Setting input delay on channel " + str(channel) +
                  " dline taps T0:" + str(tap0) + " T1:" + str(tap1))
        self.IDELAY_DEBUG.write(0x8, 0b1)
        sleep(0.1)
        self.IDELAY_DEBUG.write(0x8, 0b0)
        # plog.debug("DP0: "+bin(dp0))
        # plog.debug("DP1: " + bin(dp1))
        self.IDELAY_DEBUG.write(0x0, 0x1)
        sleep(0.05)
        plog.debug("OBS0: " + bin(self.IDELAY_DEBUG.read(0x0)))

    def uencode(self, val, length):
        """[DEPRECIATED] - NOT USED - 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
Exemplo n.º 23
0
    X_PADDING4 = int((KERNEL_WIDTH4 - 1 / 2))
    Y_PADDING4 = int((KERNEL_HEIGHT4 - 1) / 2)
else:
    X_PADDING4 = 0
    Y_PADDING4 = 0

OUT_CH4 = 10
OUT_WIDTH4 = int((IN_WIDTH4 + 2 * X_PADDING4 - KERNEL_WIDTH4) / X_STRIDE4 + 1)
OUT_HEIGHT4 = int((IN_HEIGHT4 + 2 * Y_PADDING4 - KERNEL_HEIGHT4) / Y_STRIDE4 +
                  1)

# In[20]:

xlnk = Xlnk()

ol = Overlay("bitstream/cnn0.bit")
ol.download()
conv = ol.Conv_0
pool = ol.Pool_0
print("Overlay download finish")

# In[17]:

ol.ip_dict

# In[18]:

#input image
image = xlnk.cma_array(shape=(IN_HEIGHT1, IN_WIDTH1, IN_CH1),
                       cacheable=0,
                       dtype=np.float32)
Exemplo n.º 24
0
import os
import time
from PIL import Image
from matplotlib import pyplot
import cv2
from datetime import datetime
from pynq import Xlnk
from pynq import Overlay
from pynq.mmio import MMIO
from loader import loader
import scipy.misc
from IPython.display import display

print('FPGA Initializing...')
OVERLAY_PATH = 'overlay.bit'
overlay = Overlay(OVERLAY_PATH)
dma = overlay.axi_dma_0

xlnk = Xlnk()
nn_ctrl = MMIO(0x43c00000, length=1024)
print('Got nn_ctrl!')

## FPGA Parameters

height = 28
width = 28
pixel_bits = 8
pixels_per_line = 448 / pixel_bits
num_lines = int((height * width) / pixels_per_line)

# hostName = "localhost"
Exemplo n.º 25
0
      if vlnv in metadata.functions:
        stream_args=[]
        scalar_args=[]
        for param in sig.parameters.values():
          if type(param.annotation) is list:
            stream_args.append(wrap_arg(ba.arguments[param.name],param.annotation[0]))
          else:
            scalar_args.append(ba.arguments[param.name])
        return Call(vlnv,stream_args,scalar_args,return_type=ret_type)
      else:
        return func(*args,**kwargs)
    return wrapped_function
  return decorator

from pynq import Overlay
Overlay('base.bit').download()
from pynq.drivers import DMA
import pynq.drivers.dma
Overlay('/home/xilinx/jupyter_notebooks/PYNQ_Classification/PYNQ_SIDE/Theano/CIFAR_10/Bitstream/decorator_cifar10_16b.bit').download()

def prepare_execution(plan,dma,return_port):
  if type(plan) is Wrapper:
    d=DMAWrapper(len(dma))
    d.set_data(plan.wrapped,plan.dtype())
    dma.append(d)
    hw_switch.set_route(d.ports[1][0],return_port)
  elif type(plan) is Call:
    in_ports=metadata.functions[plan.func].in_ports
    out_ports=metadata.functions[plan.func].out_ports
    name=metadata.functions[plan.func].name
    mmio=None
Exemplo n.º 26
0
import cv2
import numpy as np
from pynq.board import Switch
from pynq import Overlay
Overlay("base.bit").download()

cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 5, (640, 480))

#for red color
# lower mask (0-10)
lower_1 = np.array([0, 100, 100])
upper_1 = np.array([10, 255, 255])

if not cap.isOpened():
    print('Camera is not open.')
    cap.open(0)
else:
    print('Start')
while cap.isOpened():
    if Switch(0).read():
        print('switch 0 read')
        break
    ret, frame = cap.read()
    if ret:
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(hsv, lower_1, upper_1)
        hsv = cv2.bitwise_and(hsv, hsv, mask=mask)
        cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)[-2]
Exemplo n.º 27
0
 def __init__(self):
     overlay = Overlay("./design_1.bit")
     self.hw_compute = overlay.DoCompute_0
import sys
import numpy as np
from time import time
import matplotlib.pyplot as plt 

sys.path.append('/home/xilinx')
from pynq import Overlay
from pynq import allocate

if __name__ == "__main__":
    print("Entry:", sys.argv[0])
    print("System argument(s):", len(sys.argv))

    print("Start of \"" + sys.argv[0] + "\"")

    ol = Overlay("/home/xilinx/IPBitFile/fp_accum.bit")
    ipfpaccum = ol.fp_accum_0
    ipDMAIn = ol.axi_dma_in_0
    ipDMAOut = ol.axi_dma_out_0

    fiSamples = open("samples_triangular_wave.txt", "r+")
    numSamples = 0
    line = fiSamples.readline()
    while line:
        numSamples = numSamples + 1
        line = fiSamples.readline()

    inBuffer0 = allocate(shape=(numSamples,), dtype=np.int32)
    outBuffer0 = allocate(shape=(numSamples,), dtype=np.int32)
    fiSamples.seek(0)
    for i in range(numSamples):
Exemplo n.º 29
0
import numpy as np
import random
from time import time
import matplotlib.pyplot as plt

sys.path.append('/home/xilinx')
from pynq import Overlay
from pynq import allocate

if __name__ == "__main__":
    print("Entry:", sys.argv[0])
    print("System argument(s):", len(sys.argv))

    print("Start of \"" + sys.argv[0] + "\"")

    ol = Overlay("/home/xilinx/IPBitFile/rsErasure.bit")
    ipFIRN11 = ol.rs_erasure_0

    # fiSamples = open("samples_triangular_wave.txt", "r+")
    outC = allocate(shape=(4, ), dtype=np.int8)
    inD = allocate(shape=(12, ), dtype=np.int8)
    survival_pattern = allocate(shape=(1, ), dtype=np.int16)
    codeid = allocate(shape=(1, ), dtype=np.int8)

    # errcnt = 0
    linecnt = 0
    # suberrcnt = [0, 0, 0, 0]
    sublincnt = [0, 0, 0, 0]

    with open('./tv_rs_erasure_in.txt', 'r') as f_in:
        for line in f_in:
Exemplo n.º 30
0
                    else:
                        scalar_args.append(ba.arguments[param.name])
                return Call(vlnv,
                            stream_args,
                            scalar_args,
                            return_type=ret_type)
            else:
                return func(*args, **kwargs)

        return wrapped_function

    return decorator


from pynq import Overlay
Overlay('base.bit').download()
from pynq.drivers import DMA
import pynq.drivers.dma
Overlay(
    '/home/xilinx/jupyter_notebooks/PYNQ_CNN/Theano/CIFAR_10/Bitstream/cifar_10.bit'
).download()


def prepare_execution(plan, dma, return_port):
    if type(plan) is Wrapper:
        d = DMAWrapper(len(dma))
        d.set_data(plan.wrapped, plan.dtype())
        dma.append(d)
        hw_switch.set_route(d.ports[1][0], return_port)
    elif type(plan) is Call:
        in_ports = metadata.functions[plan.func].in_ports
Exemplo n.º 31
0
MODE6 = 0  #0:VALID, 1:SAME
if (MODE6):
    X_PADDING6 = int((KERNEL_WIDTH6 - 1 / 2))
    Y_PADDING6 = int((KERNEL_HEIGHT6 - 1) / 2)
else:
    X_PADDING6 = 0
    Y_PADDING6 = 0

OUT_CH6 = 2
OUT_WIDTH6 = int((IN_WIDTH6 + 2 * X_PADDING6 - KERNEL_WIDTH6) / X_STRIDE6 + 1)
OUT_HEIGHT6 = int((IN_HEIGHT6 + 2 * Y_PADDING6 - KERNEL_HEIGHT6) / Y_STRIDE6 +
                  1)

xlnk = Xlnk()

ol = Overlay("ai.bit")
ol.ip_dict
ol.download()
conv = ol.Conv_0
pool = ol.Pool_0
print("Overlay download finish")

#input image
image = xlnk.cma_array(shape=(IN_HEIGHT1, IN_WIDTH1, IN_CH1),
                       cacheable=0,
                       dtype=np.float32)

#conv1
W_conv1 = xlnk.cma_array(shape=(KERNEL_HEIGHT1, KERNEL_WIDTH1, IN_CH1,
                                OUT_CH1),
                         cacheable=0,
Exemplo n.º 32
0
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
Exemplo n.º 33
0
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("SP_OVERLAY.bit", 0)
        self.OV.download()
        axi_offset = 0
        ##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
        #43c4
        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
        #43c8
        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)))
        axi_offset += 1
        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)
        #43c9
        ##Initialize IDELAY
        self.DELAY_TAPS = MMIO(axi_base_addr + (axi_offset * axi_range),
                               0x10000)

        plog.info("IDELAY: " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43ca

        ##Initialize pulse counter
        #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("PCDAT" + str(i) + " -- " +
                      hex(axi_base_addr + (axi_offset * axi_range)))
            axi_offset += 1
        #43ce
        #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("PCUT" + str(i) + " -- " + hex(axi_base_addr +
                                                     (axi_offset * axi_range)))
            axi_offset += 1
        #43d2
        #Initialize trigger controller
        self.T_UTIL = MMIO(0x41210000, 0x10000)
        self.T_UTIL.write(ch2_dir, 0x0)
        self.T_UTIL.write(ch2_data, 0x0)
        self.T_RDY_UTIL = MMIO(0x41200000, 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("STDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.ST_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.ST_UTIL.write(ch1_data, 0x0)
        plog.info("STUTIL -- " + 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("CTDAT -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        self.CT_UTIL = MMIO(axi_base_addr + (axi_offset) * axi_range,
                            axi_range)
        self.CT_UTIL.write(ch1_data, self.CT_UTIL.read(0x0) & 0b110)
        plog.info("CTUTIL -- " + hex(axi_base_addr + (axi_offset * axi_range)))
        axi_offset += 1
        #43d6
        ##Initialize time tagger
        self.TT_CONFIG = MMIO(axi_base_addr + (axi_offset * axi_range),
                              axi_range)
        self.TT_CONFIG.write(ch2_data, 0x0)
        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
        self.IDELAY_DEBUG = MMIO(axi_base_addr + (axi_offset * axi_range),
                                 axi_range)
        plog.info("IDELAY_DEBUG: " + hex(axi_base_addr +
                                         (axi_offset * axi_range)))
        axi_offset += 1
        plog.debug("AXI_RANGE -- " + hex(axi_range))
        #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
        self.pg_ch_stat = 0xF
        sleep(0.05)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #self.PG_UTIL.write(ch2_data,0x0)
        sleep(0.1)
        self.IDELAY_DEBUG.write(0x0, 0x1)
        #Initial delay valus
        self.DDs = []
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)
        self.DDs.append(0)

    def restart(self):
        self.__init__()

    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_UTIL.read(ch2_data)) == 0:  #Wait for ready
            pass
        op = self.ST_DATA.read(ch1_data) / DET_REF_CLK  #Read time
        dels = self.ST_DATA.read(
            ch2_data)  #Read start and finish fine time values
        #ADd and subtract start and end fine time values from coarse time
        #to the coarse time
        op = op + (((dels & 0xFF)) - ((dels & 0xFF00) >> 8)) * FTIME
        self.ST_UTIL.write(ch1_data, 0x0)
        return op

    ####----------------------------------------------------------------------------------####
    ####------------------Two channel photon coincidence timer----------------------------####
    def ct_arm_and_wait(self, mode):
        """Arm two channel rising edge coincidence timer and hang until time data is ready (On channel 0 and 1)

        Parameters
        ----------
        mode : :class:`int`
            Defines which channel to listen for start rising edge or either (0,1 or 2)

        Returns
        -------
        :class:`float`
            Time between rising edges (in seconds)

        """
        print("Starting CT")
        #Set which channel the hardware is listening to for the start pulse and take the submodule out of reset enabling it
        if (mode == int(LineSelectMode.DONTCARE)):
            self.CT_UTIL.write(0x0, self.CT_UTIL.read(0x0) | 0b100)
        else:
            self.CT_UTIL.write(0x0, self.CT_UTIL.read(0x0) & 0b001)
            self.CT_UTIL.write(0x0, self.CT_UTIL.read(0x0) | (int(mode) << 1))
        self.CT_UTIL.write(0x0, self.CT_UTIL.read(0x0) | 0b1)
        #Wait for the coincidence time to be ready (waits until the second pulse)
        while (self.CT_UTIL.read(ch2_data)) == 0:
            pass
        #Read coarse time
        sleep(0.1)
        coarse_time = self.CT_DATA.read(ch1_data) / DET_REF_CLK
        finetimeconcat = self.CT_DATA.read(ch2_data)  #Read fine times
        #Include fine time offsets with the coarse time
        ftime0 = finetimeconcat & 0xFF
        ftime1 = (finetimeconcat & 0xFF00) >> 8
        self.CT_UTIL.write(
            ch1_data,
            self.CT_UTIL.read(0x0)
            & 0b110)  #Disable coincidence timer by placing it in reset
        return coarse_time + (ftime0 - ftime1) * FTIME

    ####---------------------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) / DDS_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(DDS_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 * DDS_REF_CLK)

    def TT_wait_for_rdy(self):
        """Wait until time tagger tags each channel or times out (Hangs the thread)



        """
        #Wait for a transition on the data readyline
        if (self.TT_UTIL.read(ch2_data)) == 0:
            while (self.TT_UTIL.read(ch2_data)) == 0:
                pass
        else:
            while (self.TT_UTIL.read(ch2_data)) == 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 * DET_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_CONFIG.write(ch2_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
        ftt0 = self.TT_DELAY_DATA.read(ch2_data)
        stimet0 = (
            ftt0) * FTIME  #Calculate the fine time offset of the t0 signal
        plog.debug("T0FT: " + bin(ftt0))
        dels = self.TT_DELAY_DATA.read(
            ch1_data
        )  #Fine times for channels 0-3 (Each is concatenated in binary)
        #Calculating the fine time offsets for each channel
        stimet1 = ((dels & 0xFF)) * FTIME
        stimet2 = ((dels & 0xFF00) >> 8) * FTIME
        stimet3 = ((dels & 0xFF0000) >> 16) * FTIME
        stimet4 = ((dels & 0xFF000000) >> 24) * FTIME
        plog.debug("T1FT: " + bin((dels & 0xFF)))
        #Include fine time offsets with the coarse times
        cttime1 = self.TT_DATA0.read(ch1_data)
        ctime1 = cttime1 / DET_REF_CLK - stimet1 + stimet0
        ctime2 = self.TT_DATA0.read(ch2_data) / DET_REF_CLK - stimet2 + stimet0
        ctime3 = self.TT_DATA1.read(ch1_data) / DET_REF_CLK - stimet3 + stimet0
        ctime4 = self.TT_DATA1.read(ch2_data) / DET_REF_CLK - stimet4 + stimet0
        plog.debug("T1CT: " + str(cttime1))
        timeouts = (self.TT_UTIL.read(ch1_data))  #Read time outs
        #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_CONFIG.write(ch2_data, 0x0)

    def DD_idelay(self, channel, tap0, tap1):
        """Sets the input delay of the specified channel by configuring the delay line taps and the number of delay line stages to include
           Channels 4 and 5 are T0 and END TRIG
        Parameters
        ----------
        channel : :class:`int`
            Channel to delay (0-5)
        tap0 : :class:`int`
            Delay line tap (0-31)
         tap1 : :class:`int`
            Delay line cascaded tap (0-31)
        """

        concattaps = tap0 | (tap1 << 5)
        self.DDs[channel] = concattaps
        allconcat0 = self.DDs[4] | (self.DDs[0] << 10) | (self.DDs[1] << 20)
        allconcat1 = self.DDs[2] | (self.DDs[3] << 10) | (self.DDs[5] << 20)
        self.DELAY_TAPS.write(0x0, allconcat0)
        self.DELAY_TAPS.write(0x8, allconcat1)
        # if(channel <=2):
        #     dp0 = self.DELAY_TAPS.read(0x0) | (0b1111111111 << (channel*10))
        #     dp1 = dp0 & (concattaps << (channel*10))
        #     self.DELAY_TAPS.write(0x0,dp1)
        # else:
        #     dp0 = self.DELAY_TAPS.read(0x8) | (0b1111111111 << ((channel-3) * 10))
        #     dp1 = dp0 & (concattaps << ((channel-3) * 10))
        #     self.DELAY_TAPS.write(0x8, dp1)
        plog.info("Setting input delay on channel " + str(channel) +
                  " dline taps T0:" + str(tap0) + " T1:" + str(tap1))
        self.IDELAY_DEBUG.write(0x8, 0b1)
        sleep(0.1)
        self.IDELAY_DEBUG.write(0x8, 0b0)
        # plog.debug("DP0: "+bin(dp0))
        # plog.debug("DP1: " + bin(dp1))
        self.IDELAY_DEBUG.write(0x0, 0x1)
        sleep(0.05)
        plog.debug("OBS0: " + bin(self.IDELAY_DEBUG.read(0x0)))

    def uencode(self, val, length):
        """[DEPRECIATED] 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