Ejemplo 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()
Ejemplo n.º 2
0
    def __init__(self, description):
        super().__init__(description)

        # Define a Register object at address 0x0 of the core address space
        # We will use this to set bits and start the core (see start())
        # Do NOT write to __ap_ctrl unless ap_rstn has been deasserted

        self.__address = self.mmio.base_addr

        self.__ap_ctrl = Register(self.__address + self.__AP_CTRL_OFF, 32)
        self.__gie = Register(self.__address + self.__GIE_OFF, 32)
        self.__ier = Register(self.__address + self.__IER_OFF, 32)
        self.__isr = Register(self.__address + self.__ISR_OFF, 32)
Ejemplo n.º 3
0
    def config_ioswitch(self, ioswitch_pins, ioswitch_select_value):
        """Configure the IO switch.

        This method configures the IO switch based on the input parameters.

        Parameters
        ----------
        ioswitch_pins : list
            List of pins to be configured.
        ioswitch_select_value : int
            Function selection parameter.

        """
        # Read switch config
        self.write_command(CMD_READ_INTF_SWITCH_CONFIG)
        mailbox_addr = self.mmio.base_addr + MAILBOX_OFFSET
        ioswitch_config = [
            Register(addr) for addr in [mailbox_addr, mailbox_addr + 4]
        ]

        # Modify switch for requested entries
        for ix in ioswitch_pins:
            if ix < 10:
                lsb = ix * 2
                msb = ix * 2 + 1
                ioswitch_config[0][msb:lsb] = ioswitch_select_value
            else:
                lsb = (ix - 10) * 2
                msb = (ix - 10) * 2 + 1
                ioswitch_config[1][msb:lsb] = ioswitch_select_value

        # Write switch config
        self.write_command(CMD_INTF_SWITCH_CONFIG)
Ejemplo 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)
Ejemplo n.º 5
0
def set_data_width(width_option):
    """Set AXI port data width.

    We need to select the 32/64/128-bit data width for the slave registers.
    Each of the following values corresponds to a specific data width.
    The reason why we need this step, is that for some petalinux BSP's
    (e.g. `xilinx-zcu104-v2019.1-final.bsp`), the AXI lite interface width
    is not set properly. This step may not be needed for future PYNQ
    releases.

    00: 32-bit AXI data width (default)
    01: 64-bit AXI data width
    10: 128-bit AXI data width (reset value)
    11: reserved

    Parameters
    ----------
    width_option : int
        The width options ranging from 0 to 3.

    """
    if width_option not in range(4):
        raise ValueError("Data width option can only be set to 0, 1, 2, 3.")
    Register(0xFF419000)[9:8] = width_option
Ejemplo n.º 6
0
    def setup(self, expressions):
        """Configure CFGLUTs with new boolean expression.

        Parameters
        ----------
        expressions : list/dict
            The boolean expression to be configured.

        """

        if isinstance(expressions, list):
            for i in range(len(expressions)):
                self.expressions['Boolean expression {}'.format(i)] = \
                    deepcopy(expressions[i])
        elif isinstance(expressions, dict):
            self.expressions = deepcopy(expressions)
        else:
            raise ValueError("Expressions must be list or dict.")

        mailbox_addr = self.bg_mmio.base_addr
        mailbox_regs = [
            Register(addr)
            for addr in range(mailbox_addr, mailbox_addr + 4 * 64, 4)
        ]
        for offset in range(0, 32, 2):
            mailbox_regs[offset][31:0] = 0x1FFFFFF

        for index in range(0, 32):
            self.bg_mmio.write((index * 4), mailbox_regs[index][31:0])
        self.bg_mmio.write((62 * 4), 0x0000ffff)
        self.bg_mmio.write((63 * 4), (0x0000ffff | 0x80000000))
        self.bg_mmio.write((63 * 4), 0)  # was 0x0000ffff)

        for expr_label, expression in self.expressions.items():
            if not isinstance(expression, str):
                raise TypeError("Boolean expression has to be a string.")

            if "=" not in expression:
                raise ValueError(
                    "Boolean expression must have form Output = Function.")

            # Parse boolean expression into output & input string
            expr_out, expr_in = expression.split("=")
            expr_out = expr_out.strip()
            if expr_out in self.output_pins:
                raise ValueError("The same output pin should not be driven by "
                                 "multiple expressions.")
            self.output_pins.append(expr_out)
            if expr_out in self.intf_spec['output_pins']:
                output_pin_num = self.intf_spec['output_pins'][expr_out]
            else:
                raise ValueError("Invalid output pin {}.".format(expr_out))

            # Parse the used pins preserving the order
            non_unique_inputs = re.sub("\W+", " ", expr_in).strip().split(' ')
            unique_input_pins = list(OrderedDict.fromkeys(non_unique_inputs))
            if not 1 <= len(unique_input_pins) <= 5:
                raise ValueError("Expect 1 - 5 inputs for each LUT.")
            input_pins_with_dontcares = unique_input_pins[:]
            self.input_pins += unique_input_pins
            self.input_pins = list(set(self.input_pins))

            # Need 5 inputs - any unspecified inputs will be don't cares
            for i in range(len(input_pins_with_dontcares), 5):
                expr_in = '(({0}) & X{1})|(({0}) & ~X{1})'.format(expr_in, i)
                input_pins_with_dontcares.append('X{}'.format(i))

            # Map to truth table
            p0, p1, p2, p3, p4 = map(exprvar, input_pins_with_dontcares)
            expr_p = expr_in

            # Use regular expression to match and replace whole word only
            for orig_name, p_name in zip(input_pins_with_dontcares,
                                         ['p{}'.format(i) for i in range(5)]):
                expr_p = re.sub(r"\b{}\b".format(orig_name), p_name, expr_p)

            truth_table = expr2truthtable(eval(expr_p))

            # Parse truth table to send
            truth_list = str(truth_table).split("\n")
            truth_num = 0
            for i in range(32, 0, -1):
                truth_num = (truth_num << 1) + int(truth_list[i][-1])

            # Get current boolean generator bit enables
            bit_enables = self.bg_mmio.read(62 * 4)
            cfg_enables = self.bg_mmio.read(63 * 4)

            # Generate the input selects based on truth table and bit enables
            truth_table_inputs = [str(inp) for inp in truth_table.inputs]
            for i in range(5):
                lsb = i * 5
                msb = (i + 1) * 5 - 1
                if truth_table_inputs[i] in unique_input_pins:
                    if truth_table_inputs[i] in self.intf_spec[
                        'input_pins'] and truth_table_inputs[i] \
                            in self.intf_spec['input_pins']:
                        input_pin_ix = self.intf_spec['input_pins'][
                            truth_table_inputs[i]]
                    else:
                        raise ValueError("Invalid input pin "
                                         "{}.".format(truth_table_inputs[i]))
                else:
                    input_pin_ix = 0x1f
                mailbox_regs[output_pin_num * 2][msb:lsb] = input_pin_ix

            mailbox_regs[output_pin_num * 2 + 1][31:0] = truth_num
            mailbox_regs[62][31:0] = bit_enables
            mailbox_regs[62][output_pin_num] = 0

            mailbox_regs[63][31:0] = cfg_enables
            mailbox_regs[63][output_pin_num] = 1

        int_to_write_62 = int(mailbox_regs[62][31:0])
        int_to_write_63 = int(mailbox_regs[63][31:0])
        for index in range(0, 32):
            self.bg_mmio.write((index * 4), (mailbox_regs[index][31:0]))
        self.bg_mmio.write((62 * 4), int_to_write_62)
        self.bg_mmio.write((63 * 4), (int_to_write_63 | 0x80000000))
        self.bg_mmio.write((63 * 4), int_to_write_63)
Ejemplo n.º 7
0
    def setup(self, expressions, frequency_mhz=DEFAULT_CLOCK_FREQUENCY_MHZ):
        """Configure the generator with new boolean expression.

        This method will bring the generator from 'RESET' to 
        'READY' state.

        Parameters
        ----------
        expressions : list/dict
            The boolean expression to be configured.
        frequency_mhz: float
            The frequency of the captured samples, in MHz.

        """
        try:
            from pyeda.inter import exprvar
            from pyeda.inter import expr2truthtable
        except ImportError:
            raise ImportError("Using Logictools requires pyeda")

        if not MIN_CLOCK_FREQUENCY_MHZ <= frequency_mhz <= \
                MAX_CLOCK_FREQUENCY_MHZ:
            raise ValueError("Clock frequency out of range "
                             "[{}, {}]".format(MIN_CLOCK_FREQUENCY_MHZ,
                                               MAX_CLOCK_FREQUENCY_MHZ))

        if not 1 <= len(expressions) <= self.intf_spec['interface_width'] + \
                len(self.intf_spec['non_traceable_outputs']):
            raise ValueError("Too many or no Boolean expressions specified.")

        if isinstance(expressions, list):
            for i in range(len(expressions)):
                self.expressions['Boolean expression {}'.format(i)] = \
                    deepcopy(expressions[i])
        elif isinstance(expressions, dict):
            self.expressions = deepcopy(expressions)
        else:
            raise ValueError("Expressions must be list or dict.")

        mailbox_addr = self.logictools_controller.mmio.base_addr + \
            MAILBOX_OFFSET
        mailbox_regs = [
            Register(addr)
            for addr in range(mailbox_addr, mailbox_addr + 4 * 64, 4)
        ]
        for offset in range(0, 48, 2):
            mailbox_regs[offset][31:0] = 0x1FFFFFF

        for expr_label, expression in self.expressions.items():
            if not isinstance(expression, str):
                raise TypeError("Boolean expression has to be a string.")

            if "=" not in expression:
                raise ValueError(
                    "Boolean expression must have form Output = Function.")

            # Parse boolean expression into output & input string
            expr_out, expr_in = expression.split("=")
            expr_out = expr_out.strip()
            if expr_out in self.output_pins:
                raise ValueError("The same output pin should not be driven by "
                                 "multiple expressions.")
            self.output_pins.append(expr_out)
            if expr_out in self.intf_spec['traceable_io_pins']:
                output_pin_num = self.intf_spec['traceable_io_pins'][expr_out]
            elif expr_out in self.intf_spec['non_traceable_outputs']:
                output_pin_num = self.intf_spec['non_traceable_outputs'][
                    expr_out]
            else:
                raise ValueError("Invalid output pin {}.".format(expr_out))

            # Parse the used pins preserving the order
            non_unique_inputs = re.sub(r"\W+", " ", expr_in).strip().split(' ')
            unique_input_pins = list(OrderedDict.fromkeys(non_unique_inputs))
            if not 1 <= len(unique_input_pins) <= 5:
                raise ValueError("Expect 1 - 5 inputs for each LUT.")
            input_pins_with_dontcares = unique_input_pins[:]
            self.input_pins += unique_input_pins
            self.input_pins = list(set(self.input_pins))

            # Need 5 inputs - any unspecified inputs will be don't cares
            for i in range(len(input_pins_with_dontcares), 5):
                expr_in = '(({0}) & X{1})|(({0}) & ~X{1})'.format(expr_in, i)
                input_pins_with_dontcares.append('X{}'.format(i))

            # Map to truth table
            p0, p1, p2, p3, p4 = map(exprvar, input_pins_with_dontcares)
            expr_p = expr_in

            # Use regular expression to match and replace whole word only
            for orig_name, p_name in zip(input_pins_with_dontcares,
                                         ['p{}'.format(i) for i in range(5)]):
                expr_p = re.sub(r"\b{}\b".format(orig_name), p_name, expr_p)

            truth_table = expr2truthtable(eval(expr_p))

            # Parse truth table to send
            truth_list = str(truth_table).split("\n")
            truth_num = 0
            for i in range(32, 0, -1):
                truth_num = (truth_num << 1) + int(truth_list[i][-1])

            # Get current boolean generator bit enables
            self.logictools_controller.write_command(
                CMD_READ_BOOLEAN_DIRECTION)
            bit_enables = mailbox_regs[0][31:0]

            # Generate the input selects based on truth table and bit enables
            truth_table_inputs = [str(inp) for inp in truth_table.inputs]
            for i in range(5):
                lsb = i * 5
                msb = (i + 1) * 5 - 1
                if truth_table_inputs[i] in unique_input_pins:
                    if truth_table_inputs[i] in self.intf_spec[
                        'traceable_io_pins'] and truth_table_inputs[i] \
                            in self.intf_spec['traceable_io_pins']:
                        input_pin_ix = self.intf_spec['traceable_io_pins'][
                            truth_table_inputs[i]]
                    elif truth_table_inputs[i] in self.intf_spec[
                            'non_traceable_inputs']:
                        input_pin_ix = self.intf_spec['non_traceable_inputs'][
                            truth_table_inputs[i]]
                    else:
                        raise ValueError("Invalid input pin "
                                         "{}.".format(truth_table_inputs[i]))
                else:
                    input_pin_ix = 0x1f
                mailbox_regs[output_pin_num * 2][msb:lsb] = input_pin_ix

            mailbox_regs[output_pin_num * 2 + 1][31:0] = truth_num
            mailbox_regs[62][31:0] = bit_enables
            mailbox_regs[62][output_pin_num] = 0

            mailbox_regs[63][31:0] = 0
            mailbox_regs[63][output_pin_num] = 1

            # Construct the command word
            self.logictools_controller.write_command(CMD_CONFIG_BOOLEAN)

            # Prepare the waveform object
            waveform_dict = {
                'signal': [['stimulus'], {}, ['analysis']],
                'head': {
                    'text': '{}: {}'.format(expr_label, expression)
                }
            }

            # Append four inputs and one output to waveform view
            stimulus_traced = False
            for pin_name in unique_input_pins:
                if pin_name in self.intf_spec['traceable_io_pins']:
                    stimulus_traced = True
                    waveform_dict['signal'][0].append({
                        'name': pin_name,
                        'pin': pin_name
                    })
            if not stimulus_traced:
                del (waveform_dict['signal'][0])

            if expr_out in self.intf_spec['traceable_io_pins']:
                waveform_dict['signal'][-1].append({
                    'name': expr_out,
                    'pin': expr_out
                })
            else:
                del (waveform_dict['signal'][-1])

            self.waveforms[expr_label] = Waveform(
                waveform_dict,
                stimulus_group_name='stimulus',
                analysis_group_name='analysis')

        # Check used pins on the controller
        for i in self.input_pins + self.output_pins:
            if self.logictools_controller.pin_map[i] != 'UNUSED':
                raise ValueError("Pin conflict: {} already in use.".format(
                    self.logictools_controller.pin_map[i]))

        # Reserve pins only if there are no conflicts for any pin
        for i in self.output_pins:
            self.logictools_controller.pin_map[i] = 'OUTPUT'
        for i in self.input_pins:
            self.logictools_controller.pin_map[i] = 'INPUT'

        # Configure the trace analyzer and frequency
        if self.analyzer is not None:
            self.analyzer.setup(self.num_analyzer_samples, frequency_mhz)
        else:
            self.logictools_controller.clk.fclk1_mhz = frequency_mhz
        self.frequency_mhz = frequency_mhz

        # Update generator status
        self.logictools_controller.check_status()
        self.logictools_controller.steps = 0