aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/archapi.md50
-rw-r--r--docs/constraints.md37
-rw-r--r--docs/faq.md89
3 files changed, 158 insertions, 18 deletions
diff --git a/docs/archapi.md b/docs/archapi.md
index 73443c15..3c938865 100644
--- a/docs/archapi.md
+++ b/docs/archapi.md
@@ -30,15 +30,15 @@ delay_t maxDelay() const { return delay; }
### BelId
-A type representing a bel name. `BelId()` must construct a unique null-value. Must provide `==` and `!=` operators and a specialization for `std::hash<BelId>`.
+A type representing a bel name. `BelId()` must construct a unique null-value. Must provide `==`, `!=`, and `<` operators and a specialization for `std::hash<BelId>`.
### WireId
-A type representing a wire name. `WireId()` must construct a unique null-value. Must provide `==` and `!=` operators and a specialization for `std::hash<WireId>`.
+A type representing a wire name. `WireId()` must construct a unique null-value. Must provide `==`, `!=`, and `<` operators and a specialization for `std::hash<WireId>`.
### PipId
-A type representing a pip name. `PipId()` must construct a unique null-value. Must provide `==` and `!=` operators and a specialization for `std::hash<PipId>`.
+A type representing a pip name. `PipId()` must construct a unique null-value. Must provide `==`, `!=`, and `<` operators and a specialization for `std::hash<PipId>`.
### GroupId
@@ -215,14 +215,15 @@ Return true if the wire is available, i.e. can be bound to a net.
Return the net a wire is bound to.
-### NetInfo \*getConflictingWireNet(WireId wire) const
+### WireId getConflictingWireWire(WireId wire) const
-If this returns a non-nullptr, then unbinding that net
+If this returns a non-WireId(), then unbinding that wire
will make the given wire available.
-This returns nullptr if the wire is already available,
-or if there is no single net that can be unbound to make this
-wire available.
+### NetInfo \*getConflictingWireNet(WireId wire) const
+
+If this returns a non-nullptr, then unbinding that entire net
+will make the given wire available.
### DelayInfo getWireDelay(WireId wire) const
@@ -282,18 +283,23 @@ This method must also update `NetInfo::wires`.
Returns true if the given pip is available to be bound to a net.
+Users must also check if the pip destination wire is available
+with `checkWireAvail(getPipDstWire(pip))` before binding the
+pip to a net.
+
### NetInfo \*getBoundPipNet(PipId pip) const
Return the net this pip is bound to.
-### NetInfo \*getConflictingPipNet(PipId pip) const
+### WireId getConflictingPipWire(PipId pip) const
-Return the net that needs to be unbound in order to make this
-pip available.
+If this returns a non-WireId(), then unbinding that wire
+will make the given pip available.
-This does not need to (but may) return the conflicting wire if the conflict is
-limited to the conflicting wire being bound to the destination wire for this
-pip.
+### NetInfo \*getConflictingPipNet(PipId pip) const
+
+If this returns a non-nullptr, then unbinding that entire net
+will make the given pip available.
### const\_range\<PipId\> getPips() const
@@ -398,6 +404,10 @@ actual penalty used is a multiple of this value (i.e. a weighted version of this
Convert an `delay_t` to an actual real-world delay in nanoseconds.
+### DelayInfo getDelayFromNS(float v) const
+
+Convert a real-world delay in nanoseconds to a DelayInfo with equal min/max rising/falling values.
+
### uint32\_t getDelayChecksum(delay\_t v) const
Convert a `delay_t` to an integer for checksum calculations.
@@ -455,11 +465,17 @@ Cell Delay Methods
Returns the delay for the specified path through a cell in the `&delay` argument. The method returns
false if there is no timing relationship from `fromPort` to `toPort`.
-### TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
+### TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const
Return the _timing port class_ of a port. This can be a register or combinational input or output; clock input or
-output; general startpoint or endpoint; or a port ignored for timing purposes. For register ports, clockPort is set
-to the associated clock port.
+output; general startpoint or endpoint; or a port ignored for timing purposes. For register ports, clockInfoCount is set
+to the number of associated _clock edges_ that can be queried by getPortClockingInfo.
+
+### TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
+
+Return the _clocking info_ (including port name of clock, clock polarity and setup/hold/clock-to-out times) of a
+port. Where ports have more than one clock edge associated with them (such as DDR outputs), `index` can be used to obtain
+information for all edges. `index` must be in [0, clockInfoCount), behaviour is undefined otherwise.
Placer Methods
--------------
diff --git a/docs/constraints.md b/docs/constraints.md
new file mode 100644
index 00000000..263df7b6
--- /dev/null
+++ b/docs/constraints.md
@@ -0,0 +1,37 @@
+# Constraints
+
+There are three types of constraints available for end users of nextpnr.
+
+## Architecture-specific IO Cconstraints
+
+Architectures may provide support for their native (or any other) IO constraint format.
+The iCE40 architecture supports PCF constraints thus:
+
+ set_io led[0] 3
+
+and the ECP5 architecture supports a subset of LPF constraints:
+
+ LOCATE COMP "led[0]" SITE "E16";
+ IOBUF PORT "led[0]" IO_TYPE=LVCMOS25;
+
+
+## Absolute Placement Constraints
+
+nextpnr provides generic support for placement constraints by setting the Bel attribute on the cell to the name of
+the Bel you wish it to be placed at. For example:
+
+ (* BEL="X2/Y5/lc0" *)
+
+## Clock Constraints
+
+There are two ways to apply clock constraints in nextpnr. The `--clock {freq}` command line argument is used to
+apply a default frequency (in MHz) to all clocks without a more specific constraint.
+
+The Python API can apply clock constraints to specific named clocks. This is done by passing a Python file
+specifying these constraints to the `--pre-pack` command line argument. Inside the file, constraints are applied by
+calling the function `ctx.addClock` with the name of the clock and its frequency in MHz, for example:
+
+ ctx.addClock("csi_rx_i.dphy_clk", 96)
+ ctx.addClock("video_clk", 24)
+ ctx.addClock("uart_i.sys_clk_i", 12)
+
diff --git a/docs/faq.md b/docs/faq.md
index d440bba6..7b358187 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -38,7 +38,94 @@ For nextpnr we are using the following terminology.
Adding new architectures to nextpnr
-----------------------------------
-TBD
+### 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 guanrantee 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
-----------------------