FAQ === Terminology ----------- For nextpnr we are using the following terminology. ### Design Database Terminology - **Cell**: an instantiation of a physical block inside the netlist. The packer may combine or otherwise modify cells; and the placer places them onto Bels. - **Port**: an input or output of a Cell, can be connected to a single net. - **Net**: a connection between cell ports inside the netlist. One net will be routed using one or more wires inside the chip. Nets are always one bit in size, multibit nets are always split. - **Source**: The cell output port driving a given net - **Sink**: A cell input port driven by a given net - **Arc**: A source-sink-pair on a net ### Architecture Database Terminology - **Bel**: Basic Element, the functional blocks of an FPGA such as logic cells, IO cells, blockrams, etc. Up to one cell may be placed at each Bel. - **Pin**: an input or output of a Bel, permanently connected to a single wire. - **Pip**: Programmable Interconnect Point, a configurable connection in one direction between two wires - **Wire**: a fixed physical connection inside the FPGA between Pips and/or Bel pins. - **Alias**: a special automatic-on Pip to represent a permanent connection between two wires - **Group**: a collection of bels, pips, wires, and/or other groups ### Flow Terminology - **Packing**: The action of grouping cells in synthesis output into larger (logic) cells - **Placing**: The action of binding packed cells to Bels - **Routing**: The action of binding nets to wires ### Other Terminology - **Binding**: Assigning nets to wires and cells to Bels - **Path**: All the arcs connecting a FF output (or primary input) to a FF input (or primary output) Adding new architectures to nextpnr ----------------------------------- ### Implementing new architectures Each nextpnr architecture must implement the *nextpnr architecture API*. See [archapi.md](archapi.md) for a complete reference of the architecture API. ### Delay Estimates Each architecture must implement a `estimateDelay()` method that estimates the expected delay for a path from given `src` to `dst` wires. *It is very important that this method slightly overestimates the expected delay.* Furthermore, it should overestimate the expected delay by a slightly larger margin for longer paths than for shorter paths. Otherwise there will be performance issues with the router. The delays estimates returned by that method should also be as fine-grain as possible. It definitely pays off to spend some time improving the `estimateDelay()` for your architecture once implementing small designs work. ### Ripup Information The `getConflictingWireWire()`, `getConflictingWireNet()`, `getConflictingPipWire()`, and `getConflictingPipNet()` methods are used by the router to determine which resources to rip up in order to make a given routing resource (wire or pip) available. The architecture must guarantee that the following invariants hold. **Invariant 1:** ``` if (!ctx->checkWireAvail(wire)) { WireId w = getConflictingWireWire(wire); if (w != WireId()) { ctx->unbindWire(w); assert(ctx->checkWireAvail(wire)); } } ``` **Invariant 2:** ``` if (!ctx->checkWireAvail(wire)) { NetInfo *n = getConflictingWireNet(wire); if (n != nullptr) { for (auto &it : n->wires) ctx->unbindWire(it.first); assert(ctx->checkWireAvail(wire)); } } ``` **Invariant 3:** ``` if (!ctx->checkPipAvail(pip)) { WireId w = getConflictingPipWire(pip); if (w != WireId()) { ctx->unbindWire(w); assert(ctx->checkPipAvail(pip)); } } ``` **Invariant 4:** ``` if (!ctx->checkPipAvail(pip)) { NetInfo *n = getConflictingPipNet(pip); if (n != nullptr) { for (auto &it : n->wires) ctx->unbindWire(it.first); assert(ctx->checkPipAvail(pip)); } } ``` **Invariant 5:** ``` if (ctx->checkWireAvail(wire)) { // bind is guaranteed to succeed ctx->bindWire(wire, net, strength); } ``` **Invariant 6:** ``` if (ctx->checkPipAvail(pip) && ctx->checkWireAvail(ctx->getPipDstWire(pip))) { // bind is guaranteed to succeed ctx->bindPip(pip, net, strength); } ``` Nextpnr and other tools ----------------------- ### Which toolchain should I use and why? * If you wish to do new **research** into FPGA architectures, or other similar topics, we suggest you look at using [Verilog to Routing](https://verilogtorouting.org). If you want to use nextpnr, you might also be able to use the [Generic Arch](generic.md). * If you are developing FPGA code in **Verilog** for a **Lattice iCE40** and need an open source toolchain, we suggest you use [Yosys](http://www.clifford.at/yosys/) and nextpnr. * If you are developing FPGA code in **Verilog** for a **Lattice iCE40** with Yosys and the **existing arachne-pnr toolchain**, we suggest you start thinking about migrating to nextpnr. * If you are developing Verilog FPGA code targeted at the Lattice ECP5 and need an open source toolchain, there is also stable ECP5 support in Yosys and nextpnr. * If you are developing FPGA code in **VHDL** you may wish to look at the [ghdlsynth-beta](https://github.com/tgingold/ghdlsynth-beta) experimental VHDL frontend for Yosys. ### Why didn't you just improve [arachne-pnr](https://github.com/cseed/arachne-pnr)? [arachne-pnr](https://github.com/cseed/arachne-pnr) was originally developed as part of [Project IceStorm](http://www.clifford.at/icestorm/) to demonstrate it was possible to create an open source place and route tool for the iCE40 FPGAs that actually produced valid bitstreams. For its original purpose, it has served the community extremely well. However, it was never designed to support multiple different FPGA families, nor more complicated timing driven placement and routing used by most commercial place and route tools. It felt like extending arachne-pnr was not going to be the best path forward, so it was decided to build nextpnr as replacement. ### arachne-pnr does X better! If you have a use case which prevents you from switching to nextpnr from arachne, we want to hear about it! Please create an issue and we will do our best to solve the problem! We want nextpnr to be a suitable replacement for anyone who is currently a user of arachne-pnr, and it is important to bear in mind that arachne-pnr is no longer in active development. ### Why are you not just contributing to [Verilog to Routing](https://verilogtorouting.org)? We believe that [Verilog to Routing](https://verilogtorouting.org) is a great toolchain and many of the nextpnr developers have made (and continue to make) contributions to the project. VtR is an extremely flexible toolchain but focuses on research around FPGA architecture and algorithm development. If your goal is research, then we very much encourage you to look into VtR further! nextpnr takes a different approach by focusing on users developing FPGA code for current FPGAs. We also believe that support for real architectures will enable interesting new research. nextpnr (like all place and route tools) depends heavily on research groups like the VtR developers to investigate and push forward FPGA placement and routing algorithms in new and exciting ways. #### What is VPR? VPR is the "place and route" tool from Verilog To Routing. It has a similar role in an FPGA development flow as nextpnr. ### What about [SymbiFlow](http://symbiflow.github.io)? For the moment [SymbiFlow](http://github.com/SymbiFlow) is concentrating on extending VPR to work with real world architectures. nextpnr may or may not become a part of SymbiFlow in the future. ### What is [Project Trellis](https://github.com/SymbiFlow/prjtrellis)? [Project Trellis](https://github.com/SymbiFlow/prjtrellis) is the effort to document the bitstream format for the Lattice ECP5 series of FPGAs. It also includes tools for ECP5 bitstream generation. Project Trellis is used by nextpnr to build the ECP5 chip database and enable support for creation of bitstreams for these parts. ### What is [Project X-Ray](https://github.com/SymbiFlow/prjxray)? [Project X-Ray](https://github.com/SymbiFlow/prjxray) is the effort to document the bi
/*
             LUFA Library
     Copyright (C) Dean Camera, 2017.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

/*
  Copyright 2017  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaims all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *
 *  Header file for XMEGANVM.c.
 */

#ifndef _XMEGA_NVM_
#define _XMEGA_NVM_

	/* Includes: */
		#include <avr/io.h>
		#include <avr/interrupt.h>
		#include <stdbool.h>

		#include <LUFA/Common/Common.h>

		#include "XPROGProtocol.h"
		#include "XPROGTarget.h"
		#include "Config/AppConfig.h"

	/* Preprocessor Checks: */
		#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
			#undef ENABLE_ISP_PROTOCOL

			#if !defined(ENABLE_XPROG_PROTOCOL)
				#define ENABLE_XPROG_PROTOCOL
			#endif
		#endif

	/* Defines: */
		#define XMEGA_CRC_LENGTH_BYTES               3

		#define XMEGA_NVM_REG_ADDR0                  0x00
		#define XMEGA_NVM_REG_ADDR1                  0x01
		#define XMEGA_NVM_REG_ADDR2                  0x02
		#define XMEGA_NVM_REG_DAT0                   0x04
		#define XMEGA_NVM_REG_DAT1                   0x05
		#define XMEGA_NVM_REG_DAT2                   0x06
		#define XMEGA_NVM_REG_CMD                    0x0A
		#define XMEGA_NVM_REG_CTRLA                  0x0B
		#define XMEGA_NVM_REG_CTRLB                  0x0C
		#define XMEGA_NVM_REG_INTCTRL                0x0D
		#define XMEGA_NVM_REG_STATUS                 0x0F
		#define XMEGA_NVM_REG_LOCKBITS               0x10

		#define XMEGA_NVM_BIT_CTRLA_CMDEX            (1 << 0)

		#define XMEGA_NVM_CMD_NOOP                   0x00
		#define XMEGA_NVM_CMD_CHIPERASE              0x40
		#define XMEGA_NVM_CMD_READNVM                0x43
		#define XMEGA_NVM_CMD_LOADFLASHPAGEBUFF      0x23
		#define XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF     0x26
		#define XMEGA_NVM_CMD_ERASEFLASHPAGE         0x2B
		#define XMEGA_NVM_CMD_WRITEFLASHPAGE         0x2E
		#define XMEGA_NVM_CMD_ERASEWRITEFLASH        0x2F
		#define XMEGA_NVM_CMD_FLASHCRC               0x78
		#define XMEGA_NVM_CMD_ERASEAPPSEC            0x20
		#define XMEGA_NVM_CMD_ERASEAPPSECPAGE        0x22
		#define XMEGA_NVM_CMD_WRITEAPPSECPAGE        0x24
		#define XMEGA_NVM_CMD_ERASEWRITEAPPSECPAGE   0x25
		#define XMEGA_NVM_CMD_APPCRC                 0x38
		#define XMEGA_NVM_CMD_ERASEBOOTSEC           0x68
		#define XMEGA_NVM_CMD_ERASEBOOTSECPAGE       0x2A
		#define XMEGA_NVM_CMD_WRITEBOOTSECPAGE       0x2C
		#define XMEGA_NVM_CMD_ERASEWRITEBOOTSECPAGE  0x2D
		#define XMEGA_NVM_CMD_BOOTCRC                0x39
		#define XMEGA_NVM_CMD_READUSERSIG            0x03
		#define XMEGA_NVM_CMD_ERASEUSERSIG           0x18
		#define XMEGA_NVM_CMD_WRITEUSERSIG           0x1A
		#define XMEGA_NVM_CMD_READCALIBRATION        0x02
		#define XMEGA_NVM_CMD_READFUSE               0x07
		#define XMEGA_NVM_CMD_WRITEFUSE              0x4C
		#define XMEGA_NVM_CMD_WRITELOCK              0x08
		#define XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF     0x33
		#define XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF    0x36
		#define XMEGA_NVM_CMD_ERASEEEPROM            0x30
		#define XMEGA_NVM_CMD_ERASEEEPROMPAGE        0x32
		#define XMEGA_NVM_CMD_WRITEEEPROMPAGE        0x34
		#define XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE   0x35
		#define XMEGA_NVM_CMD_READEEPROM             0x06

	/* Function Prototypes: */
		bool XMEGANVM_WaitWhileNVMBusBusy(void);
		bool XMEGANVM_WaitWhileNVMControllerBusy(void);
		bool XMEGANVM_EnablePDI(void);
		void XMEGANVM_DisablePDI(void);
		bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand,
			                       uint32_t* const CRCDest);
		bool XMEGANVM_ReadMemory(const uint32_t ReadAddress,
		                         uint8_t* ReadBuffer,
		                         uint16_t ReadSize);
		bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand,
		                              const uint32_t WriteAddress,
		                              const uint8_t Byte);
		bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand,
		                              const uint8_t EraseBuffCommand,
		                              const uint8_t WritePageCommand,
		                              const uint8_t PageMode,
		                              const uint32_t WriteAddress,
		                              const uint8_t* WriteBuffer,
		                              uint16_t WriteSize);
		bool XMEGANVM_EraseMemory(const uint8_t EraseCommand,
		                          const uint32_t Address);

		#if defined(INCLUDE_FROM_XMEGANVM_C)
			static void XMEGANVM_SendNVMRegAddress(const uint8_t Register);
			static void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress);
		#endif

#endif