# nextpnr Generic Architecture Instead of implementing the [C++ API](archapi.md), you can programmatically build up a description of an FPGA using the generic architecture and the Python API. A basic packer is provided that supports LUTs, flipflops and IO buffer insertion. Packing could also be implemented using the Python API. At present there is no support for cell timing in the generic architecture. This will be worked on in the future. ## Python API All identifiers (`IdString`) are automatically converted to and from a Python string, so no manual conversion is required. Argument names are included in the Python bindings, so named arguments may be used. ### void addWire(IdString name, IdString type, int x, int y); Adds a wire with a name, type (for user purposes only, ignored by all nextpnr code other than the UI) to the FPGA description. x and y give a nominal location of the wire for delay estimation purposes. Delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is not of importance. ### addPip(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay, Loc loc); Adds a pip (programmable connection between two named wires). Pip delays that correspond to delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is otherwise not of importance. Loc is constructed using `Loc(x, y, z)`. 'z' for pips is only important if region constraints (e.g. for partial reconfiguration regions) are used. ### void addAlias(IdString name, IdString type, IdString srcWire, IdString dstWire, DelayInfo delay); Adds a wire alias (fixed connection between two named wires). Alias delays that correspond to delay estimates are important for router performance (as the router uses an A* type algorithm), even if timing is otherwise not of importance. ### void addBel(IdString name, IdString type, Loc loc, bool gb); Adds a bel to the FPGA description. Bel type should match the type of cells in the netlist that are placed at this bel (see below for information on special bel types supported by the packer). Loc is constructed using `Loc(x, y, z)` and must be unique. ### void addBelInput(IdString bel, IdString name, IdString wire); ### void addBelOutput(IdString bel, IdString name, IdString wire); ### void addBelInout(IdString bel, IdString name, IdString wire); Adds an input, output or inout pin to a bel, with an associated wire. Note that both `bel` and `wire` must have been created before calling this function. ### void addGroupBel(IdString group, IdString bel); ### void addGroupWire(IdString group, IdString wire); ### void addGroupPip(IdString group, IdString pip); ### void addGroupGroup(IdString group, IdString grp); Add a bel, wire, pip or subgroup to a group, which will be created if it doesn't already exist. Groups are purely for visual presentation purposes in the user interface and are not used by any place-and-route algorithms. ### void addDecalGraphic(DecalId decal, const GraphicElement &graphic); Add a graphic element to a _decal_, a reusable drawing that may be used to represent multiple wires, pips, bels or groups in the UI (with different offsets). The decal will be created if it doesn't already exist ### void setWireDecal(WireId wire, DecalXY decalxy); ### void setPipDecal(PipId pip, DecalXY decalxy); ### void setBelDecal(BelId bel, DecalXY decalxy); ### void setGroupDecal(GroupId group, DecalXY decalxy); Sets the decal ID and offset for a wire, bel, pip or group in the UI. ### void setWireAttr(IdString wire, IdString key, const std::string &value); ### void setPipAttr(IdString pip, IdString key, const std::string &value); ### void setBelAttr(IdString bel, IdString key, const std::string &value); Sets an attribute on a wire, pip or bel. Attributes are displayed in the tree view in the UI, but have no bearing on place-and-route itself. ### void setLutK(int K); Sets the number of input pins a LUT in the architecture has. Only affects the generic packer, if a custom packer or no packer is used this value has no effect - there is no need for the architecture to have LUTs at all in this case. ### void setDelayScaling(double scale, double offset); Set the linear scaling vs distance and fixed offset (both values in nanoseconds) for routing delay estimates. Delay estimates that correlate to pip delays, even if they have no bearing to reality, are important for reasonable routing runtime. ### void addCellTimingClock(IdString cell, IdString port); Set the timing class of a port on a particular cell to a clock input. _NOTE: All cell timing functions apply to an individual named cell and not a cell type. This is because cell-specific configuration might affect timing, e.g. whether or not the register is used for a slice._ ### void addCellTimingDelay(IdString cell, IdString fromPort, IdString toPort, DelayInfo delay); Specify the combinational delay between two ports of a cell, and set the timing class of those ports as combinational input/output. ### void addCellTimingSetupHold(IdString cell, IdString port, IdString clock, DelayInfo setup, DelayInfo hold); Specify setup and hold timings for a port of a cell, and set the timing class of that port as register input. ### void addCellTimingClockToOut(IdString cell, IdString port, IdString clock, DelayInfo clktoq); Specify clock-to-out time for a port of a cell, and set the timing class of that port as register output. ## Generic Packer The generic packer combines K-input LUTs (`LUT` cells) and simple D-type flip flops (`DFF` cells) (posedge clock only, no set/reset or enable) into a `GENERIC_SLICE` cell. It also inserts `GENERIC_IOB`s onto any top level IO pins without an IO buffer. Constrained IOBs can be implemented by instantiating `GENERIC_IOB` and setting the `BEL` attribute to an IO location. Thus, the architecture should provide bels with the following ports in order to use the generic packer: - `GENERIC_SLICE` bels with `CLK` input, `I[0]` .. `I[K-1]` LUT inputs, `F` LUT output and `Q` FF output (N.B. both LUT and FF outputs are not available at the same time, to represent the constraints of some FPGAs). - `GENERIC_IOB` bels with `I` output buffer input, `EN` output enable input, and `O` input buffer output. See [prims.v](../generic/synth/prims.v) for Verilog simulation models for all these cells. [synth_generic.tcl](../generic/synth/synth_generic.tcl) can be used with Yosys to perform synthesis to the generic `LUT` and `DFF` cells which the generic packer supports. Invoke it using `tcl synth_generic.tcl K out.json` where _K_ is the number of LUT inputs and _out.json_ the name of the JSON file to write. The generic packer in its current state is intended for experimentation and proof-of-concept tests. It is _not_ intended to make use of all FPGA features or support complex designs. In these cases a proper [Arch API](archapi.md) implementation is strongly recommended. ## Validity Checks The following constraints are enforced by the generic architecture during placement. - `GENERIC_SLICE` bels may only have one clock signal per tile (xy location) - If the `PACK_GROUP` attribute is set to a non-zero value on cells, then only cells with the same `PACK_GROUP` attribute (or `PACK_GROUP` negative or unset) may share a tile. This could be set by the Python API or during synthesis. ## Implementation Example An artificial, procedural architecture is included in the [generic/examples](../generic/examples) folder. [simple.py](../generic/examples/simple.py) sets up the architecture, and [report.py](../generic/examples/report.py) saves post-place-and-route design to a text file (in place of bitstream generation). [simple.sh](../generic/examples/simple.sh) can be used to synthesise and place-and-route a simple blinky for this architecture.
# Bootmagic

There are three separate but related features that allow you to change the behavior of your keyboard without reflashing. While each of them have similar functionality, it is accessed in different ways depending on how your keyboard is configured.

**Bootmagic** is a system for configuring your keyboard while it initializes. To trigger a Bootmagic command, hold down the Bootmagic key and one or more command keys.

**Bootmagic Keycodes** are prefixed with `MAGIC_`, and allow you to access the Bootmagic functionality *after* your keyboard has initialized. To use the keycodes, assign them to your keymap as you would any other keycode.

**Command**, formerly known as **Magic**, is another feature that allows you to control different aspects of your keyboard. While it shares some functionality with Bootmagic, it also allows you to do things that Bootmagic does not, such as printing version information to the console. For more information, see [Command](feature_command.md).

On some keyboards Bootmagic is disabled by default. If this is the case, it must be explicitly enabled in your `rules.mk` with:

```make
BOOTMAGIC_ENABLE = full
```

?> You may see `yes` being used in place of `full`, and this is okay. However, `yes` is deprecated, and ideally `full` (or `lite`) should be used instead.

Additionally, you can use [Bootmagic Lite](#bootmagic-lite) (a scaled down, very basic version of Bootmagic) by adding the following to your `rules.mk` file:

```make
BOOTMAGIC_ENABLE = lite
```

## Hotkeys

Hold down the Bootmagic key (Space by default) and the desired hotkey while plugging in your keyboard. For example, holding Space+`B` should cause it to enter the bootloader.

|Hotkey            |Description                                  |
|------------------|---------------------------------------------|
|Escape            |Ignore Bootmagic configuration in EEPROM     |
|`B`               |Enter the bootloader                         |
|`D`               |Toggle debugging over serial                 |
|`X`               |Toggle key matrix debugging                  |
|`K`               |Toggle keyboard debugging                    |
|`M`               |Toggle mouse debugging                       |
|Backspace         |Clear the EEPROM                             |
|Caps Lock         |Toggle treating Caps Lock as Left Control    |
|Left Control      |Toggle swapping Caps Lock and Left Control   |
|Left Alt          |Toggle swapping Left Alt and Left GUI        |
|Right Alt         |Toggle swapping Right Alt and Right GUI      |
|Left GUI          |Toggle the GUI keys (useful when gaming)     |
|<code>&#96;</code>|Toggle swapping <code>&#96;</code> and Escape|
|`\`               |Toggle swapping `\` and Backspace            |
|`N`               |Toggle N-Key Rollover (NKRO)                 |
|`0`               |Make layer 0 the default layer               |
|`1`               |Make layer 1 the default layer               |
|`2`               |Make layer 2 the default layer               |
|`3`               |Make layer 3 the default layer               |
|`4`               |Make layer 4 the default layer               |
|`5`               |Make layer 5 the default layer               |
|`6`               |Make layer 6 the default layer               |
|`7`               |Make layer 7 the default layer               |

## Keycodes

|Keycode                           |Aliases  |Description                               |
|----------------------------------|---------|------------------------------------------|
|`MAGIC_CAPSLOCK_TO_CONTROL`       |         |Treat Caps Lock as Left Control           |
|`MAGIC_UNCAPSLOCK_TO_CONTROL`     |         |Stop treating Caps Lock as Left Control   |
|`MAGIC_HOST_NKRO`                 |         |Force N-Key Rollover (NKRO) on            |
|`MAGIC_UNHOST_NKRO`               |         |Force NKRO off                            |
|`MAGIC_TOGGLE_NKRO`               |         |Turn NKRO on or off                       |
|`MAGIC_NO_GUI`                    |         |Disable the GUI keys (useful when gaming) |
|`MAGIC_UNNO_GUI`                  |         |Enable the GUI keys                       |
|`MAGIC_SWAP_ALT_GUI`              |`AG_SWAP`|Swap Alt and GUI on both sides (for macOS)|
|`MAGIC_UNSWAP_ALT_GUI`            |`AG_NORM`|Unswap Left Alt and Left GUI              |
|`MAGIC_TOGGLE_ALT_GUI`            |`AG_TOGG`|Toggle Left Alt and GUI swap              |
|`MAGIC_SWAP_BACKSLASH_BACKSPACE`  |         |Swap `\` and Backspace                    |
|`MAGIC_UNSWAP_BACKSLASH_BACKSPACE`|         |Unswap `\` and Backspace                  |
|`MAGIC_SWAP_CONTROL_CAPSLOCK`     |         |Swap Left Control and Caps Lock           |
|`MAGIC_UNSWAP_CONTROL_CAPSLOCK`   |         |Unswap Left Control and Caps Lock         |
|`MAGIC_SWAP_GRAVE_ESC`            |         |Swap <code>&#96;</code> and Escape        |
|`MAGIC_UNSWAP_GRAVE_ESC`          |         |Unswap <code>&#96;</code> and Escape      |
|`MAGIC_SWAP_LALT_LGUI`            |         |Swap Left Alt and Left GUI                |
|`MAGIC_UNSWAP_LALT_LGUI`          |         |Unswap Left Alt and Left GUI              |
|`MAGIC_SWAP_RALT_RGUI`            |         |Swap Right Alt and Right GUI              |
|`MAGIC_UNSWAP_RALT_RGUI`          |         |Unswap Right Alt and Right GUI            |

## Configuration

If you would like to change the hotkey assignments for Bootmagic, `#define` these in your `config.h` at either the keyboard or keymap level.

|Define                                  |Default      |Description                                        |
|----------------------------------------|-------------|---------------------------------------------------|
|`BOOTMAGIC_KEY_SALT`                    |`KC_SPACE`   |The Bootmagic key                                  |
|`BOOTMAGIC_KEY_SKIP`                    |`KC_ESC`     |Ignore Bootmagic configuration in EEPROM           |
|`BOOTMAGIC_KEY_EEPROM_CLEAR`            |`KC_BSPACE`  |Clear the EEPROM configuration                     |
|`BOOTMAGIC_KEY_BOOTLOADER`              |`KC_B`       |Enter the bootloader                               |
|`BOOTMAGIC_KEY_DEBUG_ENABLE`            |`KC_D`       |Toggle debugging over serial                       |
|`BOOTMAGIC_KEY_DEBUG_MATRIX`            |`KC_X`       |Toggle matrix debugging                            |
|`BOOTMAGIC_KEY_DEBUG_KEYBOARD`          |`KC_K`       |Toggle keyboard debugging                          |
|`BOOTMAGIC_KEY_DEBUG_MOUSE`             |`KC_M`       |Toggle mouse debugging                             |
|`BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK`   |`KC_LCTRL`   |Swap Left Control and Caps Lock                    |
|`BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL`     |`KC_CAPSLOCK`|Toggle treating Caps Lock as Left Control          |
|`BOOTMAGIC_KEY_SWAP_LALT_LGUI`          |`KC_LALT`    |Toggle swapping Left Alt and Left GUI (for macOS)  |
|`BOOTMAGIC_KEY_SWAP_RALT_RGUI`          |`KC_RALT`    |Toggle swapping Right Alt and Right GUI (for macOS)|
|`BOOTMAGIC_KEY_NO_GUI`                  |`KC_LGUI`    |Toggle the GUI keys (useful when gaming)           |
|`BOOTMAGIC_KEY_SWAP_GRAVE_ESC`          |`KC_GRAVE`   |Toggle swapping <code>&#96;</code> and Escape      |
|`BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE`|`KC_BSLASH`  |Toggle swapping `\` and Backspace                  |
|`BOOTMAGIC_HOST_NKRO`                   |`KC_N`       |Toggle N-Key Rollover (NKRO)                       |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_0`         |`KC_0`       |Make layer 0 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_1`         |`KC_1`       |Make layer 1 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_2`         |`KC_2`       |Make layer 2 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_3`         |`KC_3`       |Make layer 3 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_4`         |`KC_4`       |Make layer 4 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_5`         |`KC_5`       |Make layer 5 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_6`         |`KC_6`       |Make layer 6 the default layer                     |
|`BOOTMAGIC_KEY_DEFAULT_LAYER_7`         |`KC_7`       |Make layer 7 the default layer                     |

# Bootmagic Lite

In addition to the full blown Bootmagic feature, is the Bootmagic Lite feature that only handles jumping into the bootloader.  This is great for boards that don't have a physical reset button but you need a way to jump into the bootloader, and don't want to deal with the headache that Bootmagic can cause.

To enable this version of Bootmagic, you need to enable it in your `rules.mk` with:

```make
BOOTMAGIC_ENABLE = lite
```

Additionally, you may want to specify which key to use.  This is especially useful for keyboards that have unusual matrices.  To do so, you need to specify the row and column of the key that you want to use. Add these entries to your `config.h` file:

```c
#define BOOTMAGIC_LITE_ROW 0
#define BOOTMAGIC_LITE_COLUMN 1
```

By default, these are set to 0 and 0, which is usually the "ESC" key on a majority of keyboards.

And to trigger the bootloader, you hold this key down when plugging the keyboard in. Just the single key. 

## Advanced Bootmagic Lite

The `bootmagic_lite` function is defined weakly, so that you can replace this in your code, if you need.  A great example of this is the Zeal60 boards that have some additional handling needed.

To replace the function, all you need to do is add something like this to your code:

```c
void bootmagic_lite(void) {
    matrix_scan();
    wait_ms(DEBOUNCING_DELAY * 2);
    matrix_scan();

    if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
      // Jump to bootloader.
      bootloader_jump();
    }
}
```

You can additional feature here. For instance, resetting the eeprom or requiring additional keys to be pressed to trigger bootmagic.  Keep in mind that `bootmagic_lite` is called before a majority of features are initialized in the firmware.