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 __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)
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)
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 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
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)
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