Exemplo n.º 1
0
    def __init__(self, bitfile, **kwargs):
        """Initializes a new sharedmemOverlay object.

        """
        # The following lines do some path searching to enable a
        # PYNQ-Like API for Overlays. For example, without these
        # lines you cannot call sharedmemOverlay('sharedmem.bit') because
        # sharedmem.bit is not on the bitstream search path. The
        # following lines fix this for any non-PYNQ Overlay
        #
        # You can safely reuse, and ignore the following lines
        #
        # Get file path of the current class (i.e. /opt/python3.6/<...>/sharedmem.py)
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        # Get directory path of the current class (i.e. /opt/python3.6/<...>/sharedmem/)
        dir_path = os.path.dirname(file_path)
        # Update the bitfile path to search in dir_path
        bitfile = os.path.join(dir_path, bitfile)
        # Upload the bitfile (and parse the colocated .tcl script)
        super().__init__(bitfile, **kwargs)
        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        self.nreset()
        # Define a Register object at address 0x0 of the mmult address space
        # We will use this to set bits and start the core (see start())
        # Do NOT write to __ap_ctrl unless __resetPin has been set to __NRESET_VALUE
        self.__ap_ctrl = Register(self.mmultCore.mmio.base_addr, 32)
        self.__a_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_A_DATA, 32)
        self.__bt_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_BT_DATA, 32)
        self.__c_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_C_DATA, 32)
        self.xlnk = Xlnk()
Exemplo n.º 2
0
    def __init__(self,
                 iop_name,
                 addr_base,
                 addr_range,
                 gpio_uix,
                 mb_program,
                 intr_pin=None,
                 intr_ack_gpio=None):
        """Create a new _IOP object.

        Parameters
        ----------
        iop_name : str
            The name of the IP corresponding to the I/O Processor.
        addr_base : int
            The base address for the MMIO.
        addr_range : int
            The address range for the MMIO.
        gpio_uix : int
            The user index of the GPIO, starting from 0.
        mb_program : str
            The Microblaze program loaded for the IOP.

        """
        self.iop_name = iop_name
        self.mb_program = mb_program
        self.state = 'IDLE'
        self.gpio = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(addr_base, addr_range)
        if intr_pin and intr_ack_gpio:
            self.interrupt = _IOPInterruptEvent(intr_pin, intr_ack_gpio)

        self.program()
Exemplo n.º 3
0
    def __init__(self, description, gpio_name=None):
        """Return a new Audio object based on the hierarchy description.

        Parameters
        ----------
        description : dict
            The hierarchical description of the hierarchy
        gpio_name : str
            The name of the audio path selection GPIO. If None then the GPIO
            pin in the hierarchy is used, otherwise the gpio_name is searched
            in the list of pins on the hierarchy and the PL.gpio_dict.

        """
        super().__init__(description)

        if gpio_name is None:
            if len(self._gpio) == 0:
                raise RuntimeError('Could not find audio path select GPIO.')
            elif len(self._gpio) > 1:
                raise RuntimeError('Multiple possible audio path select GPIO.')
            pin_name = next(iter(self._gpio.keys()))
            self.gpio = getattr(self, pin_name)
        else:
            if gpio_name in self._gpio:
                self.gpio = getattr(self, gpio_name)
            elif gpio_name in PL.gpio_dict:
                pin = GPIO.get_gpio_pin(PL.gpio_dict[gpio_name]['index'])
                self.gpio = GPIO(pin, 'out')
            else:
                raise RuntimeError('Provided gpio_name not found.')

        self._ffi = cffi.FFI()
        self._libaudio = self._ffi.dlopen(LIB_SEARCH_PATH +
                                          "/sources/libaudio.so")
        self._ffi.cdef("""unsigned int Xil_Out32(unsigned int Addr,
                                                 unsigned int Value);""")
        self._ffi.cdef("""unsigned int Xil_In32(unsigned int Addr);""")
        self._ffi.cdef("""void record(unsigned int BaseAddr,
                                      unsigned int * BufAddr,
                                      unsigned int Num_Samles_32Bit);""")
        self._ffi.cdef("""void playinit(unsigned int BaseAddr,
                                    unsigned int * BufAddr,
                                    unsigned int Num_Samles_32Bit);""")
        self._ffi.cdef("""void playend(unsigned int BaseAddr,
                                    unsigned int * BufAddr,
                                    unsigned int Num_Samles_32Bit);""")
        self._ffi.cdef("""void play(unsigned int BaseAddr,
                                    unsigned int * BufAddr,
                                    unsigned int Num_Samles_32Bit);""")
        self._ffi.cdef("""void recordinit(unsigned int BaseAddr,
                                      unsigned int * BufAddr,
                                      unsigned int Num_Samles_32Bit);""")

        char_adrp = self._ffi.from_buffer(self.mmio.mem)
        self._uint_adrpv = self._ffi.cast('unsigned int', char_adrp)

        self.buffer = numpy.zeros(0).astype(numpy.int)
        self.sample_rate = 0
        self.sample_len = 0
Exemplo n.º 4
0
    def __init__(self, bitfile, **kwargs):
        """
        Constructor (load the bit file)
        """
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        dir_path = os.path.dirname(file_path)
        bitfile = os.path.join(dir_path, bitfile)
        super().__init__(bitfile, **kwargs)

        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        self.nreset()

        # For convenience
        self.__hough = self.image_processing.hough_accel_0
        self.__dma = self.image_processing.axi_dma_0

        # Define a Register object at address 0x00 of the overlay address space
        base_addr = self.__hough.mmio.base_addr
        self.__ap_ctrl = Register(base_addr, 32)
        self.__outrho_offset = Register(base_addr + self.__OUTRHO_ADDR, 32)
        self.__outtheta_offset = Register(base_addr + self.__OUTTHETA_ADDR, 32)
        self.__num_of_lines_offset = Register(base_addr + self.__NUM_OF_LINES_ADDR, 32)
        self.__segments_offset = Register(base_addr + self.__LINES_SEGMENTS_ADDR, 32)
        self.__num_of_segments_offset = Register(base_addr + self.__NUM_OF_SEGMENTS_ADDR, 32)

        # DMA transfer engine
        self.__xlnk = Xlnk()

        # Memory pre-allocation
        self.__cma_rho = self.__xlnk.cma_array(self.__LINES, np.single)
        self.__cma_theta = self.__xlnk.cma_array(self.__LINES, np.single)
        self.__cma_numoflines = self.__xlnk.cma_array(1, np.int32)
        self.__cma_segments = self.__xlnk.cma_array((self.__SEGMENTS, 4), np.int32)
        self.__cma_numofsegments = self.__xlnk.cma_array(1, np.int32)

        self.__cmabuf_dest = self.__xlnk.cma_array((self.__HEIGHT, self.__WIDTH, 3), np.uint8)
        
        # public
        self.frame = self.__xlnk.cma_array((self.__HEIGHT, self.__WIDTH, 3), np.uint8)

        # Write address of M_AXI to HLS core
        self.__outrho_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_rho.pointer)
        self.__outtheta_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_theta.pointer)
        self.__num_of_lines_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_numoflines.pointer)
        self.__segments_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_segments.pointer)
        self.__num_of_segments_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_numofsegments.pointer)

        # Performs the computation for the first time to avoid bad behavior on the first call.
        # For a small number of segments, maybe not all segments will be detected if we don't
        # call the HoughLines function for the first time here.
        self.frame[:] = cv2.imread(dir_path+'/star.png')
        self.HoughLines(20,30,80,5,30)
    def __init__(self, intr_pin, intr_ack_gpio):
        """Create a new _MBInterruptEvent object

        Parameters
        ----------
        intr_pin : str
            Name of the interrupt pin for the Microblaze.
        intr_ack_gpio : int
            Number of the GPIO pin used to clear the interrupt.

        """
        self.interrupt = Interrupt(intr_pin)
        self.gpio = GPIO(GPIO.get_gpio_pin(intr_ack_gpio), "out")
Exemplo n.º 6
0
 def bypass_stop(self):
     """Stop streaming input to output directly.
     
     Parameters
     ----------
     None
     
     Returns
     -------
     None
     
     """
     gpio_idx = GPIO.get_gpio_pin(PL.gpio_dict["audio_path_sel/Din"][0])
     gpio_pin = GPIO(gpio_idx, 'out')
     gpio_pin.write(0)
     del gpio_pin
Exemplo n.º 7
0
 def bypass_start(self):
     """Stream audio controller input directly to output.
     
     Parameters
     ----------
     None
     
     Returns
     -------
     None
     
     """
     gpio_idx = GPIO.get_gpio_pin(PL.gpio_dict["audio_path_sel/Din"][0])
     gpio_pin = GPIO(gpio_idx, 'out')
     gpio_pin.write(1)
     del gpio_pin
Exemplo n.º 8
0
    def clk(self,index):
        """Generate one rising edge clock cycle at the specified bit position.

        Parameters
        ----------
        index : integer value indicating bit position
            The bit position ranges from 0 to 31 corresponding to 
            Dout_00 to Dout_31.

        """
        if index not in range (0, 32):
            raise ValueError("bit number must be between 0 and 31.")
        else:
            clkpin = GPIO(GPIO.get_gpio_pin(index), 'out')
            clkpin.write(1)
            clkpin.write(0)
Exemplo n.º 9
0
 def init(self, mode=None, pull=None):
     if mode != None:
         if mode == self.IN:
             self._mode = self.IN
             # GPIO.setup(self.id, GPIO.IN)
             if self.pynq_gpio != None:
                 self.pynq_gpio.release()
             self.pynq_gpio = GPIO(self.id, 'in')
         elif mode == self.OUT:
             self._mode = self.OUT
             # GPIO.setup(self.id, GPIO.OUT)
             if self.pynq_gpio != None:
                 self.pynq_gpio.release()
             self.pynq_gpio = GPIO(self.id, 'out')
         else:
             raise RuntimeError("Invalid mode for pin: %s" % self.id)
Exemplo n.º 10
0
 def bypass_start(self):
     """Stream audio controller input directly to output.
     
     Parameters
     ----------
     None
     
     Returns
     -------
     None
     
     """
     gpio_idx = GPIO.get_gpio_pin(PL.gpio_dict["audio_path_sel/Din"][0])
     gpio_pin = GPIO(gpio_idx, 'out')
     gpio_pin.write(1)
     del gpio_pin
Exemplo n.º 11
0
 def bypass_stop(self):
     """Stop streaming input to output directly.
     
     Parameters
     ----------
     None
     
     Returns
     -------
     None
     
     """
     gpio_idx = GPIO.get_gpio_pin(PL.gpio_dict["audio_path_sel/Din"][0])
     gpio_pin = GPIO(gpio_idx, 'out')
     gpio_pin.write(0)
     del gpio_pin
Exemplo n.º 12
0
class UcsdOverlay(Overlay):
    """A UCSD-Overlay Superclass for PYNQ

    """
    # GPIO Reset Values
    __RESET_VALUE = 0
    __NRESET_VALUE = 1

    def __init__(self, odir, bitfile, **kwargs):
        """Initializes a new UcsdOverlay object.

        """
        # The following lines do some path searching to enable a PYNQ-Like API
        # for Overlays. For example, without these lines you cannot call
        # myFabulousOverlay('myFabulousOverlay.bit') because
        # myFabulousOverlay.bit is not on the bitstream search path. The
        # following lines fix this for any non-PYNQ Overlay
        #
        # You can safely reuse, and ignore the following lines
        #
        # Get file path of the current class (i.e. /opt/python3.6/<...>/sharedmem.py)
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        # Get directory path of the current class (i.e. /opt/python3.6/<...>/sharedmem/)
        dir_path = os.path.dirname(file_path)
        # Update the bitfile path to search in dir_path
        bitfile = os.path.join(dir_path, odir, bitfile)
        # Upload the bitfile (and parse the colocated .tcl script)
        super().__init__(bitfile, **kwargs)
        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        self.nreset()
        self._xlnk = Xlnk()

    def nreset(self):
        """Set the reset pin to self.__NRESET_VALUE to place the core into
        not-reset (usually run)

        """
        self.__resetPin.write(self.__NRESET_VALUE)

    def reset(self):
        """Set the reset pin to self.__RESET_VALUE to place the core into
        reset

        """
        self.__resetPin.write(self.__RESET_VALUE)
Exemplo n.º 13
0
    def bit_write(self,index,value): 
        """Write a value to the specified bit position.

        Parameters
        ----------
        index : integer value indicating bit position
            The bit position ranges from 0 to 31 corresponding to 
            Dout_00 to Dout_31.
        value : integer
            The value to be written, valid value being 0 or 1.

        """
        if index not in range (0, 32):
            raise ValueError("bit number must be between 0 and 31.")
        else:
            bitwrite = GPIO(GPIO.get_gpio_pin(index), 'out')
            bitwrite.write(value)
Exemplo n.º 14
0
	def download(self, partial_bit=None):
		if partial_bit is not None:
			decoupler = GPIO(int(partial_bit[len(self.PARTIAL_BITSTREAM_PATH) + 3]) + GPIO.get_gpio_base(), 'out')
			decoupler.write(1)
		super().download(partial_bit)
		if partial_bit is not None:
			decoupler.write(0)
Exemplo n.º 15
0
    def bit_read(self,index):
        """Read a value from the specified bit position.

        Parameters
        ----------
        index : integer value indicating bit position
            The bit position ranges from 0 to 31 corresponding to 
            Dout_00 to Dout_31.

        Returns
        -------
        integer
            Read value.

        """
        if index not in range (0, 32):
            raise ValueError("bit number must be between 0 and 31.")
        else:
            bitread = GPIO(GPIO.get_gpio_pin(index+32), 'in')
            result=bitread.read()
            return result
class MBInterruptEvent:
    """The class provides and asyncio Event-like interface to
    the interrupt subsystem for a Microblaze. The event is set by
    raising an interrupt and cleared using the clear function.

    Typical use is to call clear prior to sending a request to
    the Microblaze and waiting in a loop until the response is received.
    This order of operations will avoid race conditions between the
    Microblaze and the host code.

    """
    def __init__(self, intr_pin, intr_ack_gpio):
        """Create a new _MBInterruptEvent object

        Parameters
        ----------
        intr_pin : str
            Name of the interrupt pin for the Microblaze.
        intr_ack_gpio : int
            Number of the GPIO pin used to clear the interrupt.

        """
        self.interrupt = Interrupt(intr_pin)
        self.gpio = GPIO(GPIO.get_gpio_pin(intr_ack_gpio), "out")

    @asyncio.coroutine
    def wait(self):
        """Coroutine to wait until the event is set by an interrupt.

        """
        yield from self.interrupt.wait()

    def clear(self):
        """Clear the interrupt and reset the event. Resetting the event
        should be done before sending a request that will be acknowledged
        interrupts.

        """
        self.gpio.write(1)
        self.gpio.write(0)
Exemplo n.º 17
0
    def __init__(self, bitfile, **kwargs):
        super().__init__(bitfile, **kwargs)
        if self.is_loaded():
            self.iop_pmoda.mbtype = "Pmod"
            self.iop_pmodb.mbtype = "Pmod"
            self.iop_arduino.mbtype = "Arduino"
            self.iop_rpi.mbtype = "Rpi"

            self.PMODA = self.iop_pmoda.mb_info
            self.PMODB = self.iop_pmodb.mb_info
            self.ARDUINO = self.iop_arduino.mb_info
            self.RPI = self.iop_rpi.mb_info

            self.pin_select = GPIO(
                GPIO.get_gpio_pin(self.gpio_dict['pmoda_rp_pin_sel']['index']),
                "out")
            self.audio = self.audio_codec_ctrl_0
            self.audio.configure()

            self.leds = self.leds_gpio.channel1
            self.switches = self.switches_gpio.channel1
            self.buttons = self.btns_gpio.channel1
            self.leds.setlength(4)
            self.switches.setlength(2)
            self.buttons.setlength(4)
            self.leds.setdirection("out")
            self.switches.setdirection("in")
            self.buttons.setdirection("in")
            self.rgbleds = ([None] *
                            4) + [pynq.lib.RGBLED(i) for i in range(4, 6)]

            self.trace_rpi = TraceAnalyzer(
                self.trace_analyzer_pi.description['ip'],
                PYNQZ2_RPI_SPECIFICATION)
            self.trace_pmoda = TraceAnalyzer(
                self.trace_analyzer_pi.description['ip'],
                PYNQZ2_PMODA_SPECIFICATION)
            self.trace_pmodb = TraceAnalyzer(
                self.trace_analyzer_pmodb.description['ip'],
                PYNQZ2_PMODB_SPECIFICATION)
Exemplo n.º 18
0
Arquivo: audio.py Projeto: fejat/SPARK
    def __init__(self, ip='SEG_d_axi_pdm_1_S_AXI_reg', rst="audio_path_sel"):
        """Return a new Audio object.
        
        The PL is queried to get the base address and length.
        
        Parameters
        ----------
        ip : str
            The name of the IP required for the audio driver.
        rst : str
            The name of the GPIO pins used as reset for the audio driver.
        
        """
        if ip not in PL.ip_dict:
            raise LookupError("No such audio IP in the overlay.")
        if rst not in PL.gpio_dict:
            raise LookupError("No such reset pin in the overlay.")

        self.mmio = MMIO(PL.ip_dict[ip][0], PL.ip_dict[ip][1])
        self.gpio = GPIO(GPIO.get_gpio_pin(PL.gpio_dict[rst][0]), 'out')

        self._ffi = cffi.FFI()
        self._libaudio = self._ffi.dlopen(LIB_SEARCH_PATH + "/libaudio.so")
        self._ffi.cdef("""unsigned int Xil_Out32(unsigned int Addr, 
                                                 unsigned int Value);""")
        self._ffi.cdef("""unsigned int Xil_In32(unsigned int Addr);""")
        self._ffi.cdef("""void _Pynq_record(unsigned int BaseAddr, 
                                            unsigned int * BufAddr, 
                                            unsigned int Num_Samles_32Bit);""")
        self._ffi.cdef("""void _Pynq_play(unsigned int BaseAddr, 
                                          unsigned int * BufAddr, 
                                          unsigned int Num_Samles_32Bit);""")

        char_adrp = self._ffi.from_buffer(self.mmio.mem)
        self._uint_adrpv = self._ffi.cast('unsigned int', char_adrp)

        self.buffer = numpy.zeros(0).astype(numpy.int)
        self.sample_rate = 0
        self.sample_len = 0
Exemplo n.º 19
0
    def __init__(self, iop_name, addr_base, addr_range, gpio_uix, mb_program):
        """Create a new _IOP object.
        
        Parameters
        ----------
        iop_name : str
            The name of the IP corresponding to the I/O Processor.
        addr_base : int
            The base address for the MMIO.
        addr_range : int
            The address range for the MMIO.
        gpio_uix : int
            The user index of the GPIO, starting from 0.
        mb_program : str
            The Microblaze program loaded for the IOP.
        
        """
        self.iop_name = iop_name
        self.mb_program = iop_const.BIN_LOCATION + mb_program
        self.state = 'IDLE'
        self.gpio = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(addr_base, addr_range)

        self.program()
Exemplo n.º 20
0
Arquivo: iop.py Projeto: hexanoid/PYNQ
 def __init__(self, iop_name, addr_base, addr_range, gpio_uix, mb_program):
     """Create a new _IOP object.
     
     Parameters
     ----------
     iop_name : str
         The name of the IP corresponding to the I/O Processor.
     addr_base : str
         The base address for the MMIO in hex format.
     addr_range : str
         The address range for the MMIO in hex format.
     gpio_uix : int
         The user index of the GPIO, starting from 0.
     mb_program : str
         The Microblaze program loaded for the IOP.
     
     """
     self.iop_name = iop_name
     self.mb_program = iop_const.BIN_LOCATION + mb_program
     self.state = 'IDLE'
     self.gpio = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
     self.mmio = MMIO(int(addr_base, 16), int(addr_range,16))
     
     self.program()
Exemplo n.º 21
0
def test_gpio():
    """ Test whether the GPIO class is working properly.
    
    Note
    ----
    The gpio_min is the GPIO base pin number + minimum user pin
    The gpio_max is the smallest power of 2 greater than the GPIO base.
    
    """
    # Find the GPIO base pin
    for root, dirs, files in os.walk('/sys/class/gpio'):
            for name in dirs:
                if 'gpiochip' in name:
                    index = int(''.join(x for x in name if x.isdigit()))
    base = GPIO.get_gpio_base()
    gpio_min = base + general_const.GPIO_MIN_USER_PIN
    gpio_max = 2**(math.ceil(math.log(gpio_min, 2)))
            
    for index in range(gpio_min, gpio_max):
        g = GPIO(index, 'in')
        with pytest.raises(Exception) as error_infor:
            # GPIO type is 'in'. Hence g.write() is illegal. 
            # Test will pass if exception is raised.
            g.write()
        
        g = GPIO(index, 'out')
        with pytest.raises(Exception) as error_infor:
            # GPIO type is 'out'. Hence g.read() is illegal. 
            # Test will pass if exception is raised.
            g.read()
        with pytest.raises(Exception) as error_infor:
            # write() only accepts integer 0 or 1 (not 'str'). 
            # Test will pass if exception is raised.
            g.write('1')
        
        del g
Exemplo n.º 22
0
class LED:
    def __init__(self, r, g, b):
        self.r = GPIO(GPIO.get_gpio_pin(r), 'out')
        self.g = GPIO(GPIO.get_gpio_pin(g), 'out')
        self.b = GPIO(GPIO.get_gpio_pin(b), 'out')
    
    def write(self, color):
        self.r.write(color[0])
        self.g.write(color[1])
        self.b.write(color[2])
        
    def on(self):
        color = 1, 1, 1
        self.write(color)
        
    def off(self):
        color = 0, 0, 0
        self.write(color)
Exemplo n.º 23
0
def test_gpio():
    """ Test whether the GPIO class is working properly.
    
    Note
    ----
    The gpio_min is the GPIO base pin number + minimum user pin
    The gpio_max is the smallest power of 2 greater than the GPIO base.
    
    """
    # Find the GPIO base pin
    for root, dirs, files in os.walk('/sys/class/gpio'):
        for name in dirs:
            if 'gpiochip' in name:
                index = int(''.join(x for x in name if x.isdigit()))
    base = GPIO.get_gpio_base()
    gpio_min = base + general_const.GPIO_MIN_USER_PIN
    gpio_max = 2**(math.ceil(math.log(gpio_min, 2)))

    for index in range(gpio_min, gpio_max):
        g = GPIO(index, 'in')
        with pytest.raises(Exception) as error_infor:
            # GPIO type is 'in'. Hence g.write() is illegal.
            # Test will pass if exception is raised.
            g.write()

        g = GPIO(index, 'out')
        with pytest.raises(Exception) as error_infor:
            # GPIO type is 'out'. Hence g.read() is illegal.
            # Test will pass if exception is raised.
            g.read()
        with pytest.raises(Exception) as error_infor:
            # write() only accepts integer 0 or 1 (not 'str').
            # Test will pass if exception is raised.
            g.write('1')

        del g
Exemplo n.º 24
0
 def __init__(self, r, g, b):
     self.r = GPIO(GPIO.get_gpio_pin(r), 'out')
     self.g = GPIO(GPIO.get_gpio_pin(g), 'out')
     self.b = GPIO(GPIO.get_gpio_pin(b), 'out')
Exemplo n.º 25
0
class BaseOverlay(pynq.Overlay):
    """ The Base overlay for the Pynq-Z2

    This overlay is designed to interact with all of the on board peripherals
    and external interfaces of the Pynq-Z2 board. It exposes the following
    attributes:

    Attributes
    ----------
    iop_pmoda : IOP
         IO processor connected to the PMODA interface
    iop_pmodb : IOP
         IO processor connected to the PMODB interface
    iop_arduino : IOP
         IO processor connected to the Arduino interface
    iop_rpi : IOP
         IO processor connected to the RPi interface
    trace_rpi : pynq.logictools.TraceAnalyzer
        Trace analyzer block on RPi interface, controlled by PS.
    trace_pmoda : pynq.logictools.TraceAnalyzer
        Trace analyzer block on PMODA interface, controlled by PS.
    trace_pmodb : pynq.logictools.TraceAnalyzer
        Trace analyzer block on PMODB interface, controlled by PS.
    leds : AxiGPIO
         4-bit output GPIO for interacting with the green LEDs LD0-3
    buttons : AxiGPIO
         4-bit input GPIO for interacting with the buttons BTN0-3
    switches : AxiGPIO
         2-bit input GPIO for interacting with the switches SW0 and SW1
    rgbleds : [pynq.board.RGBLED]
         Wrapper for GPIO for LD4 and LD5 multicolour LEDs
    video : pynq.lib.video.HDMIWrapper
         HDMI input and output interfaces
    audio : pynq.lib.audio.Audio
         Headphone jack and on-board microphone
    pin_select : GPIO
        The pin selection between PMODA (0) and RPI header (1).

    """
    def __init__(self, bitfile, **kwargs):
        super().__init__(bitfile, **kwargs)
        if self.is_loaded():
            self.iop_pmoda.mbtype = "Pmod"
            self.iop_pmodb.mbtype = "Pmod"
            self.iop_arduino.mbtype = "Arduino"
            self.iop_rpi.mbtype = "Rpi"

            self.PMODA = self.iop_pmoda.mb_info
            self.PMODB = self.iop_pmodb.mb_info
            self.ARDUINO = self.iop_arduino.mb_info
            self.RPI = self.iop_rpi.mb_info

            self.pin_select = GPIO(
                GPIO.get_gpio_pin(self.gpio_dict['pmoda_rp_pin_sel']['index']),
                "out")
            self.audio = self.audio_codec_ctrl_0
            self.audio.configure()

            self.leds = self.leds_gpio.channel1
            self.switches = self.switches_gpio.channel1
            self.buttons = self.btns_gpio.channel1
            self.leds.setlength(4)
            self.switches.setlength(2)
            self.buttons.setlength(4)
            self.leds.setdirection("out")
            self.switches.setdirection("in")
            self.buttons.setdirection("in")
            self.rgbleds = ([None] *
                            4) + [pynq.lib.RGBLED(i) for i in range(4, 6)]

            self.trace_rpi = TraceAnalyzer(
                self.trace_analyzer_pi.description['ip'],
                PYNQZ2_RPI_SPECIFICATION)
            self.trace_pmoda = TraceAnalyzer(
                self.trace_analyzer_pi.description['ip'],
                PYNQZ2_PMODA_SPECIFICATION)
            self.trace_pmodb = TraceAnalyzer(
                self.trace_analyzer_pmodb.description['ip'],
                PYNQZ2_PMODB_SPECIFICATION)

    def select_pmoda(self):
        """Select PMODA in the shared pins.

        This is done by writing a `0` (default) to the `pin_select`
        GPIO instance.

        """
        self.pin_select.write(0)

    def select_rpi(self):
        """Select RASPBERRYPI in the shared pins.

        This is done by writing a `1` to the `pin_select`
        GPIO instance.

        """
        self.pin_select.write(1)
Exemplo n.º 26
0
Arquivo: iop.py Projeto: hexanoid/PYNQ
class _IOP:
    """This class controls the active IOP instances in the system.
    
    Attributes
    ----------
    mb_program : str
        The absolute path of the Microblaze program.
    state : str
        The status (IDLE, RUNNING, or STOPPED) of the IOP.
    gpio : GPIO
        The GPIO instance associated with the IOP.
    mmio : MMIO
        The MMIO instance associated with the IOP.
        
    """

    def __init__(self, iop_name, addr_base, addr_range, gpio_uix, mb_program):
        """Create a new _IOP object.
        
        Parameters
        ----------
        iop_name : str
            The name of the IP corresponding to the I/O Processor.
        addr_base : str
            The base address for the MMIO in hex format.
        addr_range : str
            The address range for the MMIO in hex format.
        gpio_uix : int
            The user index of the GPIO, starting from 0.
        mb_program : str
            The Microblaze program loaded for the IOP.
        
        """
        self.iop_name = iop_name
        self.mb_program = iop_const.BIN_LOCATION + mb_program
        self.state = 'IDLE'
        self.gpio = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(int(addr_base, 16), int(addr_range,16))
        
        self.program()
        
    def start(self):
        """Start the Microblaze of the current IOP.
        
        This method will update the status of the IOP.
        
        Parameters
        ----------
        None
        
        Returns
        -------
        None
        
        """
        self.state = 'RUNNING';
        self.gpio.write(0)
        
    def stop(self):
        """Stop the Microblaze of the current IOP.
        
        This method will update the status of the IOP.
        
        Parameters
        ----------
        None
        
        Returns
        -------
        None
        
        """
        self.state = 'STOPPED'
        self.gpio.write(1)
        
    def program(self):
        """This method programs the Microblaze of the IOP.
        
        This method is called in __init__(); it can also be called after that.
        It uses the attribute "self.mb_program" to program the Microblaze. 
        
        Parameters
        ----------
        None
        
        Returns
        -------
        None
        
        """
        self.stop()
        
        PL.load_ip_data(self.iop_name, self.mb_program)
        
        self.start()
Exemplo n.º 27
0
class _IOP:
    """This class controls the active IOP instances in the system.
    
    Attributes
    ----------
    mb_program : str
        The absolute path of the Microblaze program.
    state : str
        The status (IDLE, RUNNING, or STOPPED) of the IOP.
    gpio : GPIO
        The GPIO instance associated with the IOP.
    mmio : MMIO
        The MMIO instance associated with the IOP.
        
    """
    def __init__(self, iop_name, addr_base, addr_range, gpio_uix, mb_program):
        """Create a new _IOP object.
        
        Parameters
        ----------
        iop_name : str
            The name of the IP corresponding to the I/O Processor.
        addr_base : int
            The base address for the MMIO.
        addr_range : int
            The address range for the MMIO.
        gpio_uix : int
            The user index of the GPIO, starting from 0.
        mb_program : str
            The Microblaze program loaded for the IOP.
        
        """
        self.iop_name = iop_name
        self.mb_program = iop_const.BIN_LOCATION + mb_program
        self.state = 'IDLE'
        self.gpio = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(addr_base, addr_range)

        self.program()

    def start(self):
        """Start the Microblaze of the current IOP.
        
        This method will update the status of the IOP.
        
        Returns
        -------
        None
        
        """
        self.state = 'RUNNING'
        self.gpio.write(0)

    def stop(self):
        """Stop the Microblaze of the current IOP.
        
        This method will update the status of the IOP.
        
        Returns
        -------
        None
        
        """
        self.state = 'STOPPED'
        self.gpio.write(1)

    def program(self):
        """This method programs the Microblaze of the IOP.
        
        This method is called in __init__(); it can also be called after that.
        It uses the attribute "self.mb_program" to program the Microblaze.
        
        Returns
        -------
        None
        
        """
        self.stop()

        PL.load_ip_data(self.iop_name, self.mb_program)

        self.start()
class PynqMicroblaze:
    """This class controls the active Microblaze instances in the system.

    Attributes
    ----------
    ip_name : str
        The name of the IP corresponding to the Microblaze.
    rst_name : str
        The name of the reset pin for the Microblaze.
    mb_program : str
        The absolute path of the Microblaze program.
    state : str
        The status (IDLE, RUNNING, or STOPPED) of the Microblaze.
    reset_pin : GPIO
        The reset pin associated with the Microblaze.
    mmio : MMIO
        The MMIO instance associated with the Microblaze.
    interrupt : Event
        An asyncio.Event-like class for waiting on and clearing interrupts.

    """
    def __init__(self, mb_info, mb_program, force=False):
        """Create a new Microblaze object.

        It looks for active instances on the same Microblaze, and prevents 
        users from silently reloading the Microblaze program. Users are 
        notified with an exception if a program is already running on the
        selected Microblaze, to prevent unwanted behavior.

        Two cases:

        1.  No previous Microblaze program loaded in the system, 
        or users want to request another instance using the same program.
        No exception will be raised in this case.

        2.  There is a previous Microblaze program loaded in the system.
        Users want to request another instance with a different 
        program. An exception will be raised.

        Note
        ----
        When a Microblaze program is already loaded in the system, and users
        want to instantiate another object using a different Microblaze 
        program, users are in danger of losing existing objects.

        Parameters
        ----------
        mb_info : dict
            A dictionary storing Microblaze information, such as the 
            IP name and the reset name.
        mb_program : str
            The Microblaze program loaded for the processor.

        Raises
        ------
        RuntimeError
            When another Microblaze program is already loaded.

        Examples
        --------
        The `mb_info` is a dictionary storing Microblaze information:

        >>> mb_info = {'ip_name': 'mb_bram_ctrl_1',
        'rst_name': 'mb_reset_1', 
        'intr_pin_name': 'iop1/dff_en_reset_0/q', 
        'intr_ack_name': 'mb_1_intr_ack'}

        """
        ip_dict = PL.ip_dict
        gpio_dict = PL.gpio_dict
        intr_dict = PL.interrupt_pins

        # Check program path
        if not os.path.isfile(mb_program):
            raise ValueError('{} does not exist.'.format(mb_program))

        # Get IP information
        ip_name = mb_info['ip_name']
        if ip_name not in ip_dict.keys():
            raise ValueError("No such IP {}.".format(ip_name))
        addr_base = ip_dict[ip_name]['phys_addr']
        addr_range = ip_dict[ip_name]['addr_range']
        ip_state = ip_dict[ip_name]['state']

        # Get reset information
        rst_name = mb_info['rst_name']
        if rst_name not in gpio_dict.keys():
            raise ValueError("No such reset pin {}.".format(rst_name))
        gpio_uix = gpio_dict[rst_name]['index']

        # Get interrupt pin information
        if 'intr_pin_name' in mb_info:
            intr_pin_name = mb_info['intr_pin_name']
            if intr_pin_name not in intr_dict.keys():
                raise ValueError(
                    "No such interrupt pin {}.".format(intr_pin_name))
        else:
            intr_pin_name = None

        # Get interrupt ACK information
        if 'intr_ack_name' in mb_info:
            intr_ack_name = mb_info['intr_ack_name']
            if intr_ack_name not in gpio_dict.keys():
                raise ValueError(
                    "No such interrupt ACK {}.".format(intr_ack_name))
            intr_ack_gpio = gpio_dict[intr_ack_name]['index']
        else:
            intr_ack_gpio = None

        # Set basic attributes
        self.ip_name = ip_name
        self.rst_name = rst_name
        self.mb_program = mb_program
        self.state = 'IDLE'
        self.reset_pin = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(addr_base, addr_range)

        # Check to see if Microblaze in user
        if (ip_state is not None) and (ip_state != mb_program):
            if force:
                self.reset()
            else:
                raise RuntimeError(
                    'Another program {} already running.'.format(ip_state))

        # Set optional attributes
        if (intr_pin_name is not None) and (intr_ack_gpio is not None):
            self.interrupt = MBInterruptEvent(intr_pin_name, intr_ack_gpio)
        else:
            self.interrupt = None

        # Reset, program, and run
        self.program()

    def run(self):
        """Start the Microblaze to run program loaded.

        This method will update the status of the Microblaze.

        Returns
        -------
        None

        """
        self.state = 'RUNNING'
        self.reset_pin.write(0)

    def reset(self):
        """Reset the Microblaze to stop it from running.

        This method will update the status of the Microblaze.

        Returns
        -------
        None

        """
        self.state = 'STOPPED'
        self.reset_pin.write(1)

    def program(self):
        """This method programs the Microblaze.

        This method is called in __init__(); it can also be called after that.
        It uses the attribute `self.mb_program` to program the Microblaze.

        Returns
        -------
        None

        """
        self.reset()
        PL.load_ip_data(self.ip_name, self.mb_program)
        if self.interrupt:
            self.interrupt.clear()
        self.run()

    def write(self, offset, data):
        """This method write data into the shared memory of the Microblaze.

        Parameters
        ----------
        offset : int
            The beginning offset where data are written into.
        data : int/list
            A list of 32b words to be written.

        Returns
        -------
        None

        """
        if type(data) is int:
            self.mmio.write(offset, data)
        elif type(data) is list:
            for i, word in enumerate(data):
                self.mmio.write(offset + 4 * i, word)
        else:
            raise ValueError('Type of write data has to be int or lists.')

    def read(self, offset, length=1):
        """This method reads data from the shared memory of Microblaze.

        Parameters
        ----------
        offset : int
            The beginning offset where data are read from.
        length : int
            The number of data (32-bit int) to be read.

        Returns
        -------
        int/list
            An int of a list of data read from the shared memory.

        """
        if length == 1:
            return self.mmio.read(offset)
        elif length > 1:
            return [self.mmio.read(offset + 4 * i) for i in range(length)]
        else:
            raise ValueError('Length of read data has to be 1 or more.')
Exemplo n.º 29
0
# PS pin EMIO2 is connected to slot 1 RST
# PS pin EMIO3 is connected to slot 2 RST

# Linux pin number to Xilinx pin numbers are weird and have a large
# base number than can change between different releases of Linux
# The pynq base fcn will help here!
#mio_linux_number = GPIO.get_gpio_base() + 37

# EMIOs start after MIO and there
# is fixed offset for ZYNQ (54) and ZYNQ US+ (78)
# offset = 2 corresonds to mikroBUS site 1 on Click Mezzanine v1.03
#   HD_GPIO_7
# offset = 9? corresonds to mikroBUS site 2 on Click Mezzanine v1.03
#   HD_GPIO_14

emio_linux_number = GPIO.get_gpio_base() + 78 + 2

rst_pin = GPIO(emio_linux_number, 'out')


# Convert signed into unsigned from i2c read byte
def i2c_read_byte(i2c, DA, DR):
    return (0xff & i2c.read_byte_data(DA, DR))


def i2c_write_byte(i2c, DA, DR, val):
    return (i2c.write_byte_data(DA, DR, val))


# Reset is usually active LOW, hold Click in reset while I2C is setup
# and reset the i2c mux
    def __init__(self, mb_info, mb_program, force=False):
        """Create a new Microblaze object.

        It looks for active instances on the same Microblaze, and prevents 
        users from silently reloading the Microblaze program. Users are 
        notified with an exception if a program is already running on the
        selected Microblaze, to prevent unwanted behavior.

        Two cases:

        1.  No previous Microblaze program loaded in the system, 
        or users want to request another instance using the same program.
        No exception will be raised in this case.

        2.  There is a previous Microblaze program loaded in the system.
        Users want to request another instance with a different 
        program. An exception will be raised.

        Note
        ----
        When a Microblaze program is already loaded in the system, and users
        want to instantiate another object using a different Microblaze 
        program, users are in danger of losing existing objects.

        Parameters
        ----------
        mb_info : dict
            A dictionary storing Microblaze information, such as the 
            IP name and the reset name.
        mb_program : str
            The Microblaze program loaded for the processor.

        Raises
        ------
        RuntimeError
            When another Microblaze program is already loaded.

        Examples
        --------
        The `mb_info` is a dictionary storing Microblaze information:

        >>> mb_info = {'ip_name': 'mb_bram_ctrl_1',
        'rst_name': 'mb_reset_1', 
        'intr_pin_name': 'iop1/dff_en_reset_0/q', 
        'intr_ack_name': 'mb_1_intr_ack'}

        """
        ip_dict = PL.ip_dict
        gpio_dict = PL.gpio_dict
        intr_dict = PL.interrupt_pins

        # Check program path
        if not os.path.isfile(mb_program):
            raise ValueError('{} does not exist.'.format(mb_program))

        # Get IP information
        ip_name = mb_info['ip_name']
        if ip_name not in ip_dict.keys():
            raise ValueError("No such IP {}.".format(ip_name))
        addr_base = ip_dict[ip_name]['phys_addr']
        addr_range = ip_dict[ip_name]['addr_range']
        ip_state = ip_dict[ip_name]['state']

        # Get reset information
        rst_name = mb_info['rst_name']
        if rst_name not in gpio_dict.keys():
            raise ValueError("No such reset pin {}.".format(rst_name))
        gpio_uix = gpio_dict[rst_name]['index']

        # Get interrupt pin information
        if 'intr_pin_name' in mb_info:
            intr_pin_name = mb_info['intr_pin_name']
            if intr_pin_name not in intr_dict.keys():
                raise ValueError(
                    "No such interrupt pin {}.".format(intr_pin_name))
        else:
            intr_pin_name = None

        # Get interrupt ACK information
        if 'intr_ack_name' in mb_info:
            intr_ack_name = mb_info['intr_ack_name']
            if intr_ack_name not in gpio_dict.keys():
                raise ValueError(
                    "No such interrupt ACK {}.".format(intr_ack_name))
            intr_ack_gpio = gpio_dict[intr_ack_name]['index']
        else:
            intr_ack_gpio = None

        # Set basic attributes
        self.ip_name = ip_name
        self.rst_name = rst_name
        self.mb_program = mb_program
        self.state = 'IDLE'
        self.reset_pin = GPIO(GPIO.get_gpio_pin(gpio_uix), "out")
        self.mmio = MMIO(addr_base, addr_range)

        # Check to see if Microblaze in user
        if (ip_state is not None) and (ip_state != mb_program):
            if force:
                self.reset()
            else:
                raise RuntimeError(
                    'Another program {} already running.'.format(ip_state))

        # Set optional attributes
        if (intr_pin_name is not None) and (intr_ack_gpio is not None):
            self.interrupt = MBInterruptEvent(intr_pin_name, intr_ack_gpio)
        else:
            self.interrupt = None

        # Reset, program, and run
        self.program()
Exemplo n.º 31
0
class ioOverlay(Overlay):
    """A simple Physical IO Overlay for PYNQ.
        
        This overlay is implemented with a single CtrlLoop core
        connected directly to the ARM Core AXI interface.
        
        """
    __RESET_VALUE = 0
    __NRESET_VALUE = 1
    
    """ For convenince, we define register offsets that are scraped from
        the HLS implementation header files.
        
        """
    __IO_AP_CTRL_OFF = 0x00
    __IO_AP_CTRL_START_IDX = 0
    __IO_AP_CTRL_DONE_IDX  = 1
    __IO_AP_CTRL_IDLE_IDX  = 2
    __IO_AP_CTRL_READY_IDX = 3
    __IO_AP_CTRL_AUTORESTART_IDX = 7
    
    __IO_GIE_OFF     = 0x04
    __IO_IER_OFF     = 0x08
    __IO_ISR_OFF     = 0x0C
    
    """These define the 'reg' argument to the 'io' HLS function.  The
        memory space defined here is shared between the HLS core and the
        ARM PS.
        
        """
    __IO_REG_OFF = 0x200
    __IO_REG_LEN = 0x100
    def __init__(self, bitfile, **kwargs):
        """Initializes a new ioOverlay object.
            
            """
        # The following lines do some path searching to enable a
        # PYNQ-Like API for Overlays. For example, without these
        # lines you cannot call ioOverlay('io.bit') because
        # io.bit is not on the bitstream search path. The
        # following lines fix this for any non-PYNQ Overlay
        #
        # You can safely reuse, and ignore the following lines
        #
        # Get file path of the current class (i.e. /opt/python3.6/<...>/stream.py)
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        # Get directory path of the current class (i.e. /opt/python3.6/<...>/stream/)
        dir_path = os.path.dirname(file_path)
        # Update the bitfile path to search in dir_path
        bitfile = os.path.join(dir_path, bitfile)
        # Upload the bitfile (and parse the colocated .tcl script)
        super().__init__(bitfile, **kwargs)
        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        # Define a Register object at address 0x0 of the IO address space
        # We will use this to set bits and start the core (see start())
        # Do NOT write to __ap_ctrl unless __resetPin has been set to __NRESET_VALUE
        self.nreset()
        self.__ap_ctrl = Register(self.ioCore.mmio.base_addr, 32)
        self.__hls_reg = MMIO(self.ioCore.mmio.base_addr + self.__IO_REG_OFF,
                              self.__IO_REG_LEN)
    
    def __set_autorestart(self):
        """ Set the autorestart bit of the HLS core
            """
        self.__ap_ctrl[self.__IO_AP_CTRL_AUTORESTART_IDX] = 1
    
    def __clear_autorestart(self):
        """ Clear the autorestart bit
            """
        self.__ap_ctrl[self.__IO_AP_CTRL_AUTORESTART_IDX] = 0
    
    def __start(self):
        """Raise AP_START and enable the HLS core
            
            """
        self.__ap_ctrl[self.__IO_AP_CTRL_START_IDX] = 1
    
    def __stop(self):
        """Lower AP_START and disable the HLS core
            
            """
        self.__ap_ctrl[self.__IO_AP_CTRL_START_IDX] = 0
    
    def nreset(self):
        """Set the reset pin to self.__NRESET_VALUE to place the core into
            not-reset (usually run)
            
            """
        self.__resetPin.write(self.__NRESET_VALUE)
    
    def reset(self):
        """Set the reset pin to self.__RESET_VALUE to place the core into
            reset
            
            """
        self.__resetPin.write(self.__RESET_VALUE)
    
    def launch(self):
        """ Start and detatch computation on the io HLS core
            
            Returns
            -------
            Nothing
            
            """
        self.__set_autorestart()
        self.__start()
        return
    
    def land(self):
        """ Re-Connect and Terminate Computation on the io HLS core
            
            Returns
            -------
            The 4-bit value representing the value of the buttons.
            
            """
        self.__clear_autorestart()
        while(not self.__ap_ctrl[self.__IO_AP_CTRL_DONE_IDX]):
            pass
        self.__stop()
        return self.__hls_reg.read(0)
    
    def run(self):
        """ Launch computation on the io HLS core
            
            Returns
            -------
            The 4-bit value representing the value of the buttons.
            
            """
        self.__start()
        while(not self.__ap_ctrl[self.__IO_AP_CTRL_DONE_IDX]):
            pass
        self.__stop()
        return self.__hls_reg.read(0)
Exemplo n.º 32
0
class Pin:
    IN = 0
    OUT = 1
    LOW = 0
    HIGH = 1
    PULL_NONE = 0
    PULL_UP = 1
    PULL_DOWN = 2

    id = None
    _value = LOW
    _mode = IN

    pynq_gpio = None

    def __init__(self, pin_id):
        self.id = pin_id

    def __repr__(self):
        return str(self.id)

    def __eq__(self, other):
        return self.id == other

    def init(self, mode=None, pull=None):
        if mode != None:
            if mode == self.IN:
                self._mode = self.IN
                # GPIO.setup(self.id, GPIO.IN)
                if self.pynq_gpio != None:
                    self.pynq_gpio.release()
                self.pynq_gpio = GPIO(self.id, 'in')
            elif mode == self.OUT:
                self._mode = self.OUT
                # GPIO.setup(self.id, GPIO.OUT)
                if self.pynq_gpio != None:
                    self.pynq_gpio.release()
                self.pynq_gpio = GPIO(self.id, 'out')
            else:
                raise RuntimeError("Invalid mode for pin: %s" % self.id)
        # if pull != None:
        #     if self._mode != self.IN:
        #         raise RuntimeError("Cannot set pull resistor on output")
        #     if pull == self.PULL_UP:
        #         GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        #     elif pull == self.PULL_DOWN:
        #         GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
        #     else:
        #         raise RuntimeError("Invalid pull for pin: %s" % self.id)

    def value(self, val=None):
        if val != None:
            if val == self.LOW:
                self._value = val
                # GPIO.output(self.id, val)
                self.pynq_gpio.write(val)
            elif val == self.HIGH:
                self._value = val
                # GPIO.output(self.id, val)
                self.pynq_gpio.write(val)
            else:
                raise RuntimeError("Invalid value for pin")
        else:
            # return GPIO.input(self.id)
            return self.pynq_gpio.read()
Exemplo n.º 33
0
class houghOverlay(Overlay):
    """
    This overlay contains the inferface to the PL
    image processing filter. It extracts the edges
    of the image, the lines polar parameters and the
    lines segments as well. The image size is 640x480. 
    """

    __HEIGHT = 480
    __WIDTH = 640
    __LINES = 100
    __SEGMENTS = 200

    __RESET_VALUE = 0
    __NRESET_VALUE = 1

    # Registers offset
    __HOUGH_AP_CTRL_OFF = 0x00
    __HOUGH_AP_CTRL_START_IDX = 0
    __HOUGH_AP_CTRL_DONE_IDX = 1
    __HOUGH_AP_CTRL_IDLE_IDX = 2
    __HOUGH_AP_CTRL_READY_IDX = 3

    __HOUGH_GIE_OFF = 0x04
    __HOUGH_IER_OFF = 0x08
    __HOUGH_ISR_OFF = 0x0C

    # M_AXI offset
    __OUTRHO_ADDR = 0x10
    __OUTTHETA_ADDR = 0x18
    __NUM_OF_LINES_ADDR = 0x20
    __LINES_SEGMENTS_ADDR = 0x28
    __NUM_OF_SEGMENTS_ADDR = 0x30

    # S_AXILITE offset
    __EDGES_LTHR_ADDR = 0x38
    __EDGES_HTHR_ADDR = 0x40
    __LINES_THR_ADDR = 0x48
    __GAP_SIZE_ADDR = 0x50
    __MIN_LENGTH_ADDR = 0x58

    def __init__(self, bitfile, **kwargs):
        """
        Constructor (load the bit file)
        """
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        dir_path = os.path.dirname(file_path)
        bitfile = os.path.join(dir_path, bitfile)
        super().__init__(bitfile, **kwargs)

        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        self.nreset()

        # For convenience
        self.__hough = self.image_processing.hough_accel_0
        self.__dma = self.image_processing.axi_dma_0

        # Define a Register object at address 0x00 of the overlay address space
        base_addr = self.__hough.mmio.base_addr
        self.__ap_ctrl = Register(base_addr, 32)
        self.__outrho_offset = Register(base_addr + self.__OUTRHO_ADDR, 32)
        self.__outtheta_offset = Register(base_addr + self.__OUTTHETA_ADDR, 32)
        self.__num_of_lines_offset = Register(base_addr + self.__NUM_OF_LINES_ADDR, 32)
        self.__segments_offset = Register(base_addr + self.__LINES_SEGMENTS_ADDR, 32)
        self.__num_of_segments_offset = Register(base_addr + self.__NUM_OF_SEGMENTS_ADDR, 32)

        # DMA transfer engine
        self.__xlnk = Xlnk()

        # Memory pre-allocation
        self.__cma_rho = self.__xlnk.cma_array(self.__LINES, np.single)
        self.__cma_theta = self.__xlnk.cma_array(self.__LINES, np.single)
        self.__cma_numoflines = self.__xlnk.cma_array(1, np.int32)
        self.__cma_segments = self.__xlnk.cma_array((self.__SEGMENTS, 4), np.int32)
        self.__cma_numofsegments = self.__xlnk.cma_array(1, np.int32)

        self.__cmabuf_dest = self.__xlnk.cma_array((self.__HEIGHT, self.__WIDTH, 3), np.uint8)
        
        # public
        self.frame = self.__xlnk.cma_array((self.__HEIGHT, self.__WIDTH, 3), np.uint8)

        # Write address of M_AXI to HLS core
        self.__outrho_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_rho.pointer)
        self.__outtheta_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_theta.pointer)
        self.__num_of_lines_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_numoflines.pointer)
        self.__segments_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_segments.pointer)
        self.__num_of_segments_offset[31:0] = self.__xlnk.cma_get_phy_addr(self.__cma_numofsegments.pointer)

        # Performs the computation for the first time to avoid bad behavior on the first call.
        # For a small number of segments, maybe not all segments will be detected if we don't
        # call the HoughLines function for the first time here.
        self.frame[:] = cv2.imread(dir_path+'/star.png')
        self.HoughLines(20,30,80,5,30)

    def __del__(self):
        self.__cmabuf_dest.freebuffer()
        self.__cma_rho.freebuffer()
        self.__cma_theta.freebuffer()
        self.__cma_numoflines.freebuffer()
        self.__cma_segments.freebuffer()
        self.__cma_numofsegments.freebuffer()
        self.frame.freebuffer()

    def __start(self):
        """
        Raise AP_START and enable the HLS core
        """
        self.__ap_ctrl[self.__HOUGH_AP_CTRL_START_IDX] = 1
        pass

    def __stop(self):
        """
        Lower AP_START and disable the HLS core
        """
        self.__ap_ctrl[self.__HOUGH_AP_CTRL_START_IDX] = 0
        pass

    def nreset(self):
        """
        Set the reset pin to self.__NRESET_VALUE to place the core into
        not-reset (usually run)
        """
        self.__resetPin.write(self.__NRESET_VALUE)

    def reset(self):
        """
        Set the reset pin to self.__RESET_VALUE to place the core into
        reset
        """
        self.__resetPin.write(self.__RESET_VALUE)

    def __loadParameters(self, **kwargs):
        """
        Load the Hough overlay coefficients into the HLS core
        """
        edges_lthr = kwargs.get('edges_lthr')
        edges_hthr = kwargs.get('edges_hthr')
       
        lines_thr = kwargs.get('lines_thr')
        gap_size = kwargs.get('gap_size')
        min_length = kwargs.get('min_length')

        self.__hough.write(self.__EDGES_LTHR_ADDR, edges_lthr)
        self.__hough.write(self.__EDGES_HTHR_ADDR, edges_hthr)
        
        self.__hough.write(self.__LINES_THR_ADDR, lines_thr)
        self.__hough.write(self.__GAP_SIZE_ADDR, gap_size)
        self.__hough.write(self.__MIN_LENGTH_ADDR, min_length)

    def HoughLines(self, ed_lthr, ed_hthr, thr, gap, minL, canny = None):
        """
        Launch computation on the HLS core
        """
        self.__loadParameters(edges_lthr = ed_lthr, edges_hthr = ed_hthr, lines_thr = thr, gap_size = gap, min_length = minL)

        # To check when the computation will finish
        self.__cma_numofsegments[0] = -1 # impossible to have numofsegments < 0

        # FPGA --> ARM
        self.__dma.recvchannel.transfer(self.__cmabuf_dest)
        
        # ARM --> FPGA
        self.__dma.sendchannel.transfer(self.frame)

        # Raise the AP_START bit of the AP_CTRL to initiate computation
        self.__start()

        # Wait for the DMA engines to finish
        self.__dma.sendchannel.wait()
        self.__dma.recvchannel.wait()

        # delay to wait for the m_axi output
        while(self.__cma_numofsegments[0] == -1):
            continue

        # Lower the AP_START bit of the AP_CTRL to terminate computation
        self.__stop()

        # Return the values as numpy arrays
        n_lines = self.__cma_numoflines[0]
        n_segments = self.__cma_numofsegments[0]

        lines = np.zeros((n_lines,2), dtype = np.single)
        segments = np.zeros((n_segments,4), dtype = np.int32)

        lines[:,0] = self.__cma_rho[0:n_lines]
        lines[:,1] = self.__cma_theta[0:n_lines]

        segments = self.__cma_segments[0:n_segments][:]

        if (type(canny) is np.ndarray and canny.shape == (self.__HEIGHT, self.__WIDTH, 3) and canny.dtype == np.uint8):
            canny[:] = self.__cmabuf_dest[:]

        return [lines, segments]
Exemplo n.º 34
0
class sharedmemOverlay(Overlay):
    """A simple Mem-Mapped Overlay for PYNQ.

    This overlay is implemented with a single Matrix Multiply Core fed
    connected directly to the ARM Core AXI interface.

    """
    __RESET_VALUE = 0
    __NRESET_VALUE = 1
    """ For convenince, we define register offsets that are scraped from
    the HLS implementation header files.

    """
    __MMULT_AP_CTRL_OFF = 0x00
    __MMULT_AP_CTRL_START_IDX = 0
    __MMULT_AP_CTRL_DONE_IDX = 1
    __MMULT_AP_CTRL_IDLE_IDX = 2
    __MMULT_AP_CTRL_READY_IDX = 3

    __MMULT_GIE_OFF = 0x04
    __MMULT_IER_OFF = 0x08
    __MMULT_ISR_OFF = 0x0C

    __MMULT_ADDR_A_DATA = 0x10
    __MMULT_ADDR_BT_DATA = 0x18
    __MMULT_ADDR_C_DATA = 0x20

    __MMULT_A_SHAPE = (100, 100)
    __MMULT_BT_SHAPE = (100, 100)
    __MMULT_C_SHAPE = (100, 100)
    __MMULT_A_SIZE = __MMULT_A_SHAPE[0] * __MMULT_A_SHAPE[1]
    __MMULT_BT_SIZE = __MMULT_BT_SHAPE[0] * __MMULT_BT_SHAPE[1]
    __MMULT_C_SIZE = __MMULT_C_SHAPE[0] * __MMULT_C_SHAPE[1]

    def __init__(self, bitfile, **kwargs):
        """Initializes a new sharedmemOverlay object.

        """
        # The following lines do some path searching to enable a
        # PYNQ-Like API for Overlays. For example, without these
        # lines you cannot call sharedmemOverlay('sharedmem.bit') because
        # sharedmem.bit is not on the bitstream search path. The
        # following lines fix this for any non-PYNQ Overlay
        #
        # You can safely reuse, and ignore the following lines
        #
        # Get file path of the current class (i.e. /opt/python3.6/<...>/sharedmem.py)
        file_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
        # Get directory path of the current class (i.e. /opt/python3.6/<...>/sharedmem/)
        dir_path = os.path.dirname(file_path)
        # Update the bitfile path to search in dir_path
        bitfile = os.path.join(dir_path, bitfile)
        # Upload the bitfile (and parse the colocated .tcl script)
        super().__init__(bitfile, **kwargs)
        # Manually define the GPIO pin that drives reset
        self.__resetPin = GPIO(GPIO.get_gpio_pin(0), "out")
        self.nreset()
        # Define a Register object at address 0x0 of the mmult address space
        # We will use this to set bits and start the core (see start())
        # Do NOT write to __ap_ctrl unless __resetPin has been set to __NRESET_VALUE
        self.__ap_ctrl = Register(self.mmultCore.mmio.base_addr, 32)
        self.__a_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_A_DATA, 32)
        self.__bt_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_BT_DATA, 32)
        self.__c_offset = Register(
            self.mmultCore.mmio.base_addr + self.__MMULT_ADDR_C_DATA, 32)
        self.xlnk = Xlnk()

    def __start(self):
        """Raise AP_START and enable the HLS core

        """
        self.__ap_ctrl[self.__MMULT_AP_CTRL_START_IDX] = 1
        pass

    def __stop(self):
        """Lower AP_START and disable the HLS core

        """
        self.__ap_ctrl[self.__MMULT_AP_CTRL_START_IDX] = 0
        pass

    def nreset(self):
        """Set the reset pin to self.__NRESET_VALUE to place the core into
        not-reset (usually run)

        """
        self.__resetPin.write(self.__NRESET_VALUE)

    def reset(self):
        """Set the reset pin to self.__RESET_VALUE to place the core into
        reset

        """
        self.__resetPin.write(self.__RESET_VALUE)

    def run(self, A, B):
        """ Launch computation on the mmult HLS core

        Parameters
        ----------
    
        A : Numpy ndarray of at most size TODOxTODO (it will be padded)
            A buffer containing ND Array Elements to be transferred to the core

        B : Numpy ndarray of at most size TODOxTODO (it will be padded)
            A buffer containing ND Array Elements to be transferred to the core

        """
        if (not isinstance(A, np.ndarray)):
            raise TypeError("Parameter A must be an instance of "
                            "numpy.ndarray")

        if (not isinstance(B, np.ndarray)):
            raise RuntimeError("Parameter B must be an instance of "
                               "numpy.ndarray")
        sza = A.shape
        if (sza[0] > self.__MMULT_A_SHAPE[0]):
            raise RuntimeError(
                f"Dimension 0 of A must be less than or equal to"
                f"{self.__MMULT_A_SHAPE[0]}")
        if (sza[1] > self.__MMULT_A_SHAPE[1]):
            raise RuntimeError(
                f"Dimension 1 of A must be less than or equal to"
                f"{self.__MMULT_A_SHAPE[1]}")

        szb = B.shape
        if (szb[0] > self.__MMULT_BT_SHAPE[1]):
            raise RuntimeError(
                f"Dimension 0 of B must be less than or equal to"
                f"{self.__MMULT_BT_SHAPE[0]}")
        if (szb[1] > self.__MMULT_BT_SHAPE[0]):
            raise RuntimeError(
                f"Dimension 1 of B must be less than or equal to"
                f"{self.__MMULT_BT_SHAPE[1]}")

        # Check size of A
        # Check size of B
        # Allocate C
        a = self.xlnk.cma_array(self.__MMULT_A_SHAPE, "int")
        bt = self.xlnk.cma_array(self.__MMULT_BT_SHAPE, "int")
        c = self.xlnk.cma_array(self.__MMULT_C_SHAPE, "int")
        # Copy A->a
        a[:A.shape[0], :A.shape[1]] = A
        # Copy BT->bt
        bt[:B.shape[1], :B.shape[0]] = B.transpose()
        # TODO: Enable Interrupts
        # Write address of a, bt, c to HLS core
        self.__a_offset[31:0] = self.xlnk.cma_get_phy_addr(a.pointer)
        self.__bt_offset[31:0] = self.xlnk.cma_get_phy_addr(bt.pointer)
        self.__c_offset[31:0] = self.xlnk.cma_get_phy_addr(c.pointer)
        self.__start()
        # TODO: Wait for ASYNC Interrupt
        # TODO: Clear Interrupt
        import time
        time.sleep(1)
        self.__stop()
        C = np.zeros((A.shape[0], B.shape[1]), np.int32)
        # Transform C into a Numpy Array
        C[:A.shape[0], :B.shape[1]] = c[:A.shape[0], :B.shape[1]]
        a.freebuffer()
        bt.freebuffer()
        c.freebuffer()
        return C
Exemplo n.º 35
0
from pynq import GPIO
import time
import smbus

# This will minipulate a LED Ring R Click Board in Slot 1
# of the Ultra96 mikro click mezzanine board 

# Obtain the reset pin of slot 1 of the Ultra96 mikro mezzanine board
# PS pin MIO37 is connected to slot 1 RST
# PS pin MIO40 is connected to slot 2 RST

# Linux pin number to Xilinx pin numbers are weird and have a large
# base number than can change between different releases of Linux
# The pynq base fcn will help here!  base for 2018.2 was 338
mio_linux_number = GPIO.get_gpio_base() + 37

# EMIOs start after MIO and there
# is fixed offset for ZYNQ (54) and ZYNQ US+ (78)
#   emio_linux_number = GPIO.get_gpio_pin(emio_offset)

rst_pin = GPIO(mio_linux_number, 'out')

# Reset is usually active LOW
rst_pin.write(1)
time.sleep(.1)
rst_pin.write(0)
time.sleep(.1)
rst_pin.write(1)

print("Start I2C Test\n")