libtrellis Overview
====================

libtrellis is a C++ library containing utilities to manipulate ECP5 bitstreams, and the databases that correspond tile
bits to functionality (routing and configuration). Although libtrellis can be used as a standard shared library, its
primary use in Project Trellis is as a Python module (called pytrellis), imported by the fuzzing and utility scripts.
The C++ classes are bound to Python using Boost::Python.

Bitstream
---------
This class provides functionality to read and write Lattice bitstream files, parse their commands, and convert them
into a chip's configuration memory (in terms of frames and bits).

To read a bitstream, use ``read_bit`` to create a ``Bitstream`` object, then call ``deserialise_chip`` on that to
create a ``Chip``.

Chip
-----
This represents a configured FPGA, in terms of its configuration memory (``CRAM``), tiles and metadata. You can either
use ``deserialise_chip`` on a bitstream to construct a Chip from an existing bitstream, or construct a Chip by device
name or IDCODE.

The ``ChipInfo`` structure contains information for a particular FPGA device.

CRAM
-----
This class stores the entire configuration data of the FPGA, as a 2D array (frames and bits). Although the array can be
accessed directly, many cases will use ``CRAMView`` instead. ``CRAMView`` provides a read/write view of a window of the
CRAM. This is usually used to represent the configuration memory of a single tile, and takes frame and bit offsets
and lengths.

Subtracting two ``CRAMView`` s, if they are the same size, will produce a ``CRAMDelta``, a list of the changes between
the two memories. This is useful for fuzzing or comparing bitstreams.

Tile
-----
This represents a tile of the FPGA. It includes a ``CRAMView`` to represent the configuration memory of the tile.

TileConfig
-----------
This represents the actual configuration of a tile, in terms of arcs (programmable connections), config words (such as
LUT initialisation) and config enums (such as IO type). It is the result of decoding the tile CRAM content using the bit
database, and can be converted to a FASM-like format.

The contents of ``TileConfig`` are ``ConfigArc`` for connections, ``ConfigWord`` for non-routing configuration words
(which also includes single config bits), ``ConfigEnum`` for enum configurations with multiple textual values, and
``ConfigUnknown`` for unknown bits not found in the database, which are simply stored as a frame, bit reference.

The contents of a tile's configuration RAM can be converted to and from a ``TileConfig`` by using the ``tile_cram_to_config``
and ``config_to_tile_cram`` methods on the ``TileBitDatabase`` instance for the tile.

TileBitDatabase
----------------
There will always be only one ``TileBitDatabase`` for each tile type, which is enforced by requiring calling the
function ``get_tile_bitdata`` (in ``Database.cpp``) to obtain a ``shared_ptr`` to the ``TileBitDatabase``.

The ``TileBitDatabase`` stored the function of all bits in the tile, in terms of the following constructs:

 - Muxes (``MuxBits``) specify a list of arcs that can drive a given node. Each arc (``ArcData``) contains
   specifies source, sink and the list of bits that enable it as a ``BitGroup``.
 - Config words (``WordSettingBits``) specify non-routing configuration settings that are arranged as one or more bits.
   Each config bit has an associated list of bits that enable it. This would be used both for single-bit settings
   and configuration such as LUT initialisation and PLL dividers.
 - Config enums (``EnumSettingBits``) specify non-routing configuration settings that have a set of possible textual
   values, used for either modes/types (i.e. IO type) or occasionally "special" muxes not part of general routing. These
   are specified as a map between possible values and the bits that enable those values.

``TileBitDatabase`` instances can be modified during runtime, in a thread-safe way, to enable parallel fuzzing. They can
be saved back to disk using the ``save`` method.

They can also be used to convert between tile CRAM data and higher level tile config, as described above.

RoutingGraph
-------------

``RoutingGraph`` and related structures are designed to store a complete routing graph for the Chip. ``RoutingWire``
represents wires, ``RoutingArc`` represents arcs between wires and ``RoutingBel`` represents a Bel (logic element).
To reduce memory usage, ``ident_t``, an index into a string store, is used instead of using strings directly. Use
``RoutingGraph.ident`` to convert from string to ``ident_t``, and ``RoutingGraph.to_str`` to convert to a string.

DedupChipdb
-----------
This is an experimental part of libtrellis to "deduplicate" the repetition in the routing graph, by converting it to
relative coordinates and then storing identical tile locations only once. The data produced is intended to be exported
to a database for a place and route tool using the Python API.

ChipConfig
----------
ChipConfig contains the high-level configuration for the entire chip, including all tiles and metadata. It can be
directly converted to or from a high-level configuration text file. For more information see
:doc:`Text Config Documentation <textconfig>`.
