nextpnr

repository·main·Indexed 23 days ago

https://github.com/yosyshq/nextpnr

A vendor-neutral, timing-driven, open-source FPGA place and route tool. It supports various architectures, including Lattice iCE40, ECP5, Nexus, Gowin, and provides experimental support for Xilinx 7-series and Cyclone V.

Tokens
72.4K
Snippets
163
Records
345
Agent score
82%

What's inside nextpnr

  1. Overview of pybind11

    main
    pybind11 is a lightweight, header-only C++ library designed to expose C++ types in Python and vice versa. It is primarily used to create Python bindings for existing C++ code. It aims to minimize boilerplate by using compile-time introspection to infer type information, similar to Boost.Python but optimized for C++11 and newer standards. Because it is header-only, there is no need to link against additional libraries; it only requires Python (3.6+ or PyPy) and the C++ standard library.
  2. What is Binary Blob Assembler (bba)?

    main

    Binary Blob Assembler (bba) is a tool that reads a text file describing binary data and writes a binary file. It is commonly used in a workflow where a Python script generates the input text file, and the resulting binary output is linked or loaded into a C program. The binary data is typically interpreted using (packed) structs.

    Key feature: All references (pointers) are encoded as 32-bit byte offsets relative to the location of the pointer, making the resulting binary blob position-independent.

  3. Capabilities and limitations of nextpnr-machxo2

    main

    nextpnr-machxo2 is an experimental FOSS Place and Route backend for Lattice MachXO2 FPGAs.

    Known Working Features

    • Basic routing from pads to SLICEs and back.
    • Basic packing of one type of FF and LUT into half of a SLICE.
    • Using the internal oscillator OSCH as a clock.
    • LOGIC SLICE mode.

    Untested Features

    • Non-3.3V I/O standards that do not use bank VREFs.

    Planned/Missing Features

    • More intelligent/efficient packing.
    • Global Routing.
    • Secondary High Fanout Nets.
    • Edge Clocks (clock pads work, but not routed to global routing).
    • PLLs.
    • Synchronous Release Global Set/Reset Interface (SGSR).
    • Embedded Function Block (EFB).
    • All DDR-related functionality.
    • Bank VREFs.
    • Embedded Block RAM (EBR).
    • CCU2 and DPRAM SLICE modes.
  4. Understand the nextpnr netlist core structures

    main

    The nextpnr in-memory design is built around several fundamental structures that represent the physical and logical connections of an FPGA design:

    • CellInfo: Represents an instantiation of a physical block (cell) in the netlist. Currently, all cells in nextpnr are treated as blackboxes.
    • NetInfo: Represents a connection between cell ports. A net has at most one driver and zero or more users (sinks).
    • BaseCtx / Context: The top-level container that holds all cells and nets. BaseCtx is the base class, which is subclassed by Arch to become Context.
    • PortInfo: Stores metadata for cell ports, including name, direction, and the connected net.
    • PortRef: A reference used to identify the source or sink ports of a net, pointing back to a specific cell and port name.
  5. Understand type conversion strategies in pybind11

    main

    When binding C++ to Python using pybind11, you can handle data types using one of three strategies. Choosing the right one depends on whether you prioritize performance, ease of use, or native type access:

    1. Native C++ types everywhere: Use this when you want to work with C++ objects directly. You must wrap the types using pybind11-generated bindings so Python can interact with them.
    2. Native Python types everywhere: Use this when you want to work with Python objects directly. You must wrap these types so C++ functions can interact with them.
    3. Type conversion: This is often the most "natural" approach. You use native C++ types on the C++ side and native Python types on the Python side. pybind11 handles the translation automatically.

    Note on Type Conversion Performance: Because C++ and Python types typically have different memory layouts, a copy of the data must be made every time data transitions between Python and C++.

  6. Understand the Dear ImGui binding architecture

    main

    Dear ImGui separates its core logic from platform and rendering implementation. To integrate ImGui into an application, you typically need two types of bindings:

    1. Platform Bindings: Responsible for handling OS-level inputs (mouse, keyboard, gamepad), cursor shapes, timing, and windowing. Examples include imgui_impl_win32.cpp, imgui_impl_glfw.cpp, and imgui_impl_sdl.cpp.
    2. Renderer Bindings: Responsible for managing the font atlas texture and rendering the indexed textured triangles provided by ImGui. Examples include imgui_impl_dx11.cpp, imgui_impl_opengl3.cpp, and imgui_impl_vulkan.cpp.

    Some high-level frameworks (like Allegro 5 or Marmalade) provide single files that combine both Platform and Renderer responsibilities.

  7. Handle dimension differences between Eigen and NumPy vectors

    main

    Eigen and NumPy treat vectors differently, which affects how data is passed and returned:

    Passing arrays to Eigen

    • 2D NumPy Arrays: If you pass a 2D NumPy array (1xN or Nx1), the Eigen type must have matching dimensions. You cannot pass an Nx1 array to an Eigen type expecting a row vector.
    • 1D NumPy Arrays: pybind11 allows passing 1D NumPy arrays of length N to Eigen.
      • If the Eigen type can hold a column vector, it is passed as a column vector (this takes precedence).
      • If not, but the type accepts a row vector, it is passed as a row vector.
      • Example: Passing a 1D array of size 5 to Eigen::MatrixXd results in a 5x1 Eigen matrix.

    Returning Eigen vectors to NumPy

    When returning an Eigen vector, the conversion to NumPy can be ambiguous (e.g., a row vector of length 4 could be 1D or 2D). pybind11 follows these rules:

    • Compile-time vectors: If the Eigen type has either rows or columns set to 1 at compile time, pybind11 converts it to a 1D NumPy array.
    • Run-time vectors: For types that are only vectors at runtime (e.g., Eigen::MatrixXd or Eigen::Matrix<float, Dynamic, 4>), pybind11 returns a 2D NumPy array.

    If the returned dimension is not what you expect, use array.reshape(...) in Python to get the desired view.

  8. Additional pybind11 features and goodies

    main

    Beyond core mapping, pybind11 provides several advanced capabilities:

    • Lambda Support: Bind C++11 lambda functions with captured variables (capture data is stored in the resulting Python function object).
    • Efficient Data Transfer: Uses C++11 move constructors and move assignment operators.
    • Buffer Protocol: Expose internal storage of custom types to Python's buffer protocol, enabling fast conversion between C++ matrix classes (like Eigen) and NumPy without expensive copies.
    • Vectorization: Automatically vectorize functions to apply them transparently to NumPy array arguments.
    • Slicing: Support Python's slice-based access and assignment with minimal code.
    • Pickling: C++ types can be pickled and unpickled like regular Python objects with little extra effort.
    • Performance: Smaller binaries and faster compile times compared to Boost.Python due to constexpr precomputation of function signatures.
  9. Choose the appropriate FFT package version

    main

    The Ooura FFT package provides different implementations based on your hardware architecture and the dimensionality of your data:

    By Hardware Optimization

    • fft4f2d.*: Optimized for older machines that lack large CPU caches.
    • fftsg2d.* and fftsg3d.*: Optimized for modern machines with multi-level (L1, L2, etc.) caches. These versions utilize the 1D FFT routines found in fftsg.*.

    By Dimensionality

    • 1D FFT: Provided by fftsg.* (C and Fortran versions).
    • 2D FFT: Provided by fft4f2d.* (radix 4, 2) or fftsg2d.* (Split-Radix).
    • 3D FFT: Provided by fftsg3d.* (Split-Radix).
  10. Implement Cell to Bel mapping

    main

    When designing an Architecture API, you must decide how to represent the relationship between cell types and bel types. There are two primary patterns:

    1. Common Type Transformation: The packer transforms input cells into specific nextpnr cell types that have a 1-to-1 relationship with bel types. In this model, isValidBelForCellType is a simple equality check:
    bool isValidBelForCellType(IdString cell_type, BelId bel) const {
        return cell_type == getBelType(bel);
    }
    1. Fast Validity Checking: Implement a high-performance isValidBelForCellType method that determines if a specific cell type can be bound to a specific bel without requiring a 1-to-1 mapping.
  11. Handle grapheme clusters in character literals

    main

    A single grapheme (like 'é') might be represented in Unicode as multiple code points (e.g., 'e' + combining acute accent). If such a sequence is passed to a C++ function expecting a single character type, the combining character will be lost.

    To resolve this, normalize the string using unicodedata.normalize("NFC", ...) in Python before passing it to C++.

    >>> import unicodedata
    >>> combining_e_acute = "e" + "\u0301"
    >>> example.pass_wchar(unicodedata.normalize("NFC", combining_e_acute))
    'é'
  12. How the Property Browser framework works

    main

    The Property Browser is a framework designed to allow users to edit sets of properties through a browser widget. It uses a decoupled architecture consisting of three main parts:

    1. Browser Widgets: The UI component that displays properties with labels and editing widgets. The framework provides three ready-made implementations:

      • QtTreePropertyBrowser
      • QtButtonPropertyBrowser
      • QtGroupBoxPropertyBrowser
    2. Property Managers: These handle specific data types (e.g., QtIntPropertyManager for integers, QtStringPropertyManager for strings, or a variant-based manager).

    3. Editor Factories: These determine which UI widget is used to edit a property (e.g., QtSpinBoxFactory for integers or QtLineEditFactory for strings).

    To use the framework, you associate a Property Manager with a preferred Editor Factory for each property type.