| Database Development Overview | |
| ============================= | |
| A targeted approach is used to construct bitstream databases as quickly as possible. The planned flow is for every | |
| routing mux or configuration setting we want to determine, to create post-place-and-route designs for all possibilities | |
| then run them through bitstream generation and compare the outputs. | |
| NCL Files | |
| ---------- | |
| NCL files are file format used by Lattice (originating from NeoCAD), which are a textual representation of the internal | |
| design database. Although there is little documentation on them, the format is relatively straightforward. There are | |
| tools included with Diamond to convert the design database to and from a NCL file (``ncd2ncl`` and ``ncl2ncd``). These | |
| are wrapped by the script ``diamond.sh`` included in Project Trellis, that allows two possibilities: | |
| - If given a Verilog file, it will use Diamond for synthesis and PAR, and as well as a bitstream also dump the | |
| post-place-and-route design as a NCL file. This way you can inspect how the design maps to an NCL file, and the | |
| routing and configuration inside the tile. | |
| - If given a NCL file, it will skip synthesis and PAR. It will convert the NCL file to a design database, then | |
| generate a bitstream from that. | |
| In the planned fuzzing flow, we will first create a Verilog design for what we want to fuzz by hand, and convert it to | |
| an NCL file. Then we will manually create a template NCL file containing only the mux/config to be fuzzed. The Python | |
| fuzzer script will then subsitute this template file for each fuzz possibility. | |
| A template file for LUT initialisation is shown as an example: | |
| .. code-block:: none | |
| ::FROM-WRITER; | |
| design top | |
| { | |
| device | |
| { | |
| architecture sa5p00; | |
| device LFE5U-25F; | |
| package CABGA381; | |
| performance "8"; | |
| } | |
| comp SLICE_0 | |
| [,,,,A0,B0,D0,C0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,] | |
| { | |
| logical | |
| { | |
| cellmodel-name SLICE; | |
| program "MODE:LOGIC " | |
| "K0::H0=${lut_func} " | |
| "F0:F "; | |
| primitive K0 i3_4_lut; | |
| } | |
| site R2C2A; | |
| } | |
| } | |
| The NCL file contains information about the device, components and routing (routing is not included in this example). As | |
| this was from a LUT initialisation fuzzer, ${lut_func} will be replaced by a function corresponding to the LUT init bit | |
| to be fuzzed (NCL files require an expression for LUT initialisation, rather than a series of bits). | |
| Fuzzers | |
| -------- | |
| There are three types of fuzzer in use in Project Trellis. They are routing fuzzers, non-routing fuzzers and | |
| meta-fuzzers. | |
| Routing fuzzers use the helper functions in ``util/fuzz/nonrouting.py``. These will generally follow the following | |
| algorithm: | |
| - Use the Tcl API to discover all of the netnames at the target location | |
| - Use the Tcl API to discover the arcs associated with those netnames | |
| - Apply filters to remove netnames and/or arcs not applicable to the current fuzzer | |
| - For example, when fuzzing a CIB_EBR you would ensure to include CIB signals but exclude EBR signals | |
| - When fuzzing a EBR you would conversely filter out the CIB signals and include EBR signals. | |
| - Create a reference "empty" bitstream | |
| - For every arc discovered above: | |
| - Create a bitstream containing the arc using a NCL file | |
| - Compare the bitstream against the empty bitstream: | |
| - If there was a change outside the tile(s) of interest, the arc is ignored | |
| - If there was a change to any of the tile(s) of interest, add a configurable mux arc to the database of the | |
| relevant tile | |
| - If there was no change at all, add the arc as a fixed connection to the database of the first specified tile | |
| Note that routing fuzzers for special function tiles (such as PIO, EBR, etc) are primarily intended to find fixed | |
| connections to CIBs and within special functions rather than significant amounts of configurable routing, but the above | |
| algorithm is still used for consistency (and because it is not possible to know a priori whether an arc is configurable | |
| or fixed). | |
| Non-routing fuzzers are intended to fuzz configuration such as LUT initialisation, flip-flop settings or IO type. It is | |
| possible to fuzz either words or enums. Words are for settings that naturally comprise of one or more bits, such as | |
| LUT initialisation. Enums are for settings with multiple textual values. | |
| The algorithm for word settings is to create one bitstream for each word bit with that bit set, and compare to an all-zero | |
| bitstream to determine the change for that bit. These are also optionally compared against an empty bitstream with | |
| the setting/feature entirely missing to determine a default value, which is not always all-zeros. | |
| The algorithm for enum settings is to create bitstreams with all possible enum values, in each case storing the CRAM of | |
| all tiles of interest. These are then compared to determine the set of bits affected by the enum, and in each case | |
| the bit values for each possible enum value. | |
| Creating non-routing requires more work than routing fuzzers. The settings of interest, possible values, and how to | |
| create them in the Ncl or Verilog input must all be included in the fuzzer script. | |
| Finally meta-fuzzers do not do any fuzzing but perform other necessary manipulations on the database during the fuzzing | |
| flow. For example, these may copy config bits from one tile to other tile types which have identical configuration in | |
| order to reduce the time needed for fuzzing. |