.. rst-class:: break_before Writing Software ================ All the fuzz about drivers and interfaces is no use if there is no software being written! .. note:: Ensure that you have properly activated the Python environment you created when installing XiBIF. Start by navigating to ``sw/python``. You will find that there are already some files in this directory. - `regs.py`: A class representing your register block - `xibif_demo.py`: A simple script testing the link speed of the AXI-stream Note the line where the ``XibifConnection`` object is imported. This object serves as a hardware abstraction to interface with your board. .. code-block:: python from xibif import XibifConnection connection = XibifConnection(ip_address="192.168.1.10", verbose=False) connection.open() # open the ports and connect to the FPGA Register Access --------------- Now there is a connection to the board and you can already read/write your registers. However, you would have to remember all the register addresses and bitfield masks. To avoid this, there is the generated register map which is used like this: .. code-block:: python from regs import RegMap handleReg = RegMap(connection) handleReg.register_1 = 1 # set the value of register_1 handleReg.register_1_bf.field_1 = 1 # set the value of field_1 in register_1 (read-modify-write) val = handleReg.register_2 # get the value of register_2 val = handleReg.register_2.field_1 # get the value of field_1 in register_2 .. warning:: Each access to a register property will trigger a read/write operation on the FPGA. If you have defined special register access policies such as `rc` (read to clear), reading a register might clear a field that you are not interested in. .. hint:: If you want to modify multiple fields of the same register at one time, you will have to use standard masking and bit-shifting. The appropriate values are also saved in the ``RegMap``. For each register a ``_ADDR`` property specifies the register's address, and for each field the ``__MSK`` and ``__POS`` provide the values for bitfield operations. A field is read like this: .. code-block:: python rdata = connection.read(handleReg._ADDR) field_value = (rdata >> handleReg.__POS) & handleReg.__MSK and written like this: .. code-block:: python valToWrite = 1 rdata = connection.read(handleReg._ADDR) rdata = rdata & (~(handleReg.__MSK << handleReg.__POS)) rdata = rdata | (valToWrite << handleReg.__POS) connection.write(handleReg._ADDR, rdata) You can perform multiple field modifications before calling ``xibif.write()``. Streaming --------- In order to write to the AXI-stream, use: .. code-block:: python connection.write_stream(streamToWrite) To read the stream, you must specify how many bytes of data you would like to receive. Typically, one wants to read the entire content of the FIFO. Use: .. code-block:: python connection.read_status() stream = connection.read_stream(connection.fifoPl2PcFill) There is a special function, that allows to read all the data in the FIFO without specifying the size. This function is usually faster than the previous one: .. code-block:: python stream = connection.read_stream_all() It might be possible that an error occurs during streaming. To check if an error has occurred, the properties ``connection.errorPc2Pl`` and ``connection.errorPl2Pc`` can be used. The error flags are saved until a flush of the FIFOs is performed. To flush the FIFOs, use: .. code-block:: python connection.flush_stream() The following error codes are possible: .. list-table:: :header-rows: 1 :widths: 30 70 * - Error Value - Description * - ``0`` - No error occurred during streaming. * - ``1`` - An AXI-Error on the AXI-Master interface occurred during streaming. * - ``2`` - The FIFO overflowed during streaming. This can happen if the PC or PL is not fast enough to read the data. * - ``3`` - Both an AXI-Error and a FIFO overflow occurred during streaming. AXI-Access ---------- The XiBIF platform provides a simple interface to access the AXI bus. This is useful for accessing IP blocks that are not part of the XiBIF platform. The interface is similar to the register access, but you have to specify the address of the register you want to access. To read a register, use: .. code-block:: python connection.read_axi(address) Similarly, to write to a register, use: .. code-block:: python connection.write_axi(address, value, mask=0xFFFFFFFF) The mask is optional and defaults to 0xFFFFFFFF. The mask is used to specify which bits of the register you want to write. For example, if you want to write only to the lower 16 bits of a register, you can use: .. code-block:: python connection.write_axi(address, value, 0x0000FFFF) Error Codes ~~~~~~~~~~~~ Only AXI-Addresses that are routed through the AXI Firewall IP are accessible. For Zynq-7000 platforms, the address needs to be in the range of ``0x40000000`` to ``0x4FFFFFFF``. For ZynqMP platforms, the address needs to be in the range of ``0xA0000000`` to ``0xAFFFFFFF``. Accessing other addresses will result in an error. It is further not possible to access the XiBIF IP Blocks with these functions. Calls to these addresses will result in an error.The following error codes are possible: .. list-table:: :header-rows: 1 :widths: 30 50 * - Error Code - Description * - ``AXI_ACCESS_OK`` - Access was successful. * - ``AXI_ACCESS_NOT_ALLOWED_RANGE`` - The address is not within the allowed range. It must be in the range of ``0x40000000`` to ``0x4FFFFFFF`` for Zynq-7000 platforms or ``0xA0000000`` to ``0xAFFFFFFF`` for ZynqMP platforms. * - ``AXI_ACCESS_NOT_ALLOWED_XIBIF_RANGE`` - The address is within the XiBIF reserved range and cannot be accessed. * - ``AXI_FIREWALL_ERROR`` - The AXI Firewall detected an error. * - ``AXI_FIREWALL_DATA_DEC0DEE3_DEADFA11`` - The AXI Firewall returned a specific error code indicating a data issue. If you expect to read the value ``0xDEADC0DE`` or ``0xDEADFA11`` you can disable this error by setting the property ``disable_axi_check_DEC0DEE3_DEADFA11`` to ``True``. * - ``AXI_ACCESS_ADDRESS_NOT_ALIGNED`` - The address is not aligned to 32bit values. The address must be a multiple of 4. Timeout ~~~~~~~ The timeout of the AXI Firewall IP can be configured using the command ``xibif settings``. It is specified in clock cycles of the AXI clock. The default is 100 clock cycles. .. code-block:: bash xibif settings --hw.timeout_axi_firewall_clocks 100 Debugging --------- UART ~~~~ You can enable debugging information to be printed over UART. The simplest is to print out the status information of a connected XiBIF device by calling: .. code-block:: python connection.print_status_uart() Alternatively, you can enable all ``DEBUG_PRINTF`` in the software source code by calling: .. code-block:: python connection.set_debug_uart(True) Be aware that this will result in a lot of information, as every read, write, violation and so forth will be printed. To disable the debug information again, call the function with ``False`` as an argument. .. code-block:: python connection.set_debug_uart(False) Interactive Shell ~~~~~~~~~~~~~~~~~ You can connect to a XiBIF board using an interactive shell. This lets you easily set and get registers and evaluate the AXI-Stream. Assuming you are using the default setup, type ``xibif shell`` and you should connect to the board automatically. Use ``help -v`` once the shell is open to find out which commands you can use.